This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 14661fdba07b4389e8ed7ae2539609da9841756a Author: Abhishek Mishra <[email protected]> AuthorDate: Wed Jun 10 08:03:35 2026 +0000 sched/group: implement POSIX saved-set-UID/GID semantics Adds tg_suid and tg_sgid fields to task_group_s to complete the POSIX three-field identity model (real, effective, saved-set). Updates group_inherit_identity() to propagate the new fields from parent to child task group on task creation. Fixes setuid(), setgid(), seteuid(), and setegid() to implement correct POSIX privilege transition logic: - Root (euid==0): may set any value; all three IDs updated by setuid/setgid - Non-root: may only set effective ID to real or saved value; else EPERM Signed-off-by: Abhishek Mishra <[email protected]> --- include/nuttx/sched.h | 2 ++ sched/group/group_create.c | 6 ++++-- sched/group/group_setegid.c | 17 ++++++++++++++--- sched/group/group_seteuid.c | 17 ++++++++++++++--- sched/group/group_setgid.c | 24 +++++++++++++++++++++--- sched/group/group_setuid.c | 24 +++++++++++++++++++++--- 6 files changed, 76 insertions(+), 14 deletions(-) diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 61e9c461108..ca3781995bd 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -462,6 +462,8 @@ struct task_group_s gid_t tg_gid; /* User group identity */ uid_t tg_euid; /* Effective user identity */ gid_t tg_egid; /* Effective user group identity */ + uid_t tg_suid; /* Saved set-user identity */ + gid_t tg_sgid; /* Saved set-group identity */ #endif /* Group membership *******************************************************/ diff --git a/sched/group/group_create.c b/sched/group/group_create.c index 473f6df0acf..677d818b37c 100644 --- a/sched/group/group_create.c +++ b/sched/group/group_create.c @@ -78,10 +78,12 @@ static inline void group_inherit_identity(FAR struct task_group_s *group) /* Inherit the user identity from the parent task group. */ DEBUGASSERT(group != NULL); - group->tg_uid = rgroup->tg_uid; - group->tg_gid = rgroup->tg_gid; + group->tg_uid = rgroup->tg_uid; + group->tg_gid = rgroup->tg_gid; group->tg_euid = rgroup->tg_euid; group->tg_egid = rgroup->tg_egid; + group->tg_suid = rgroup->tg_suid; + group->tg_sgid = rgroup->tg_sgid; } #else # define group_inherit_identity(group) diff --git a/sched/group/group_setegid.c b/sched/group/group_setegid.c index ac5dee2d7f9..733f11f84dc 100644 --- a/sched/group/group_setegid.c +++ b/sched/group/group_setegid.c @@ -78,9 +78,20 @@ int setegid(gid_t gid) rtcb = this_task(); rgroup = rtcb->group; - /* Set the task group's group identity. */ - DEBUGASSERT(rgroup != NULL); - rgroup->tg_egid = gid; + + if (rgroup->tg_egid == 0 || + gid == rgroup->tg_gid || gid == rgroup->tg_sgid) + { + /* Root may set any value; non-root may only set to real or saved. */ + + rgroup->tg_egid = gid; + } + else + { + set_errno(EPERM); + return ERROR; + } + return OK; } diff --git a/sched/group/group_seteuid.c b/sched/group/group_seteuid.c index b306f9a58b2..758a6355365 100644 --- a/sched/group/group_seteuid.c +++ b/sched/group/group_seteuid.c @@ -80,9 +80,20 @@ int seteuid(uid_t uid) rtcb = this_task(); rgroup = rtcb->group; - /* Set the task group's group identity. */ - DEBUGASSERT(rgroup != NULL); - rgroup->tg_euid = uid; + + if (rgroup->tg_euid == 0 || + uid == rgroup->tg_uid || uid == rgroup->tg_suid) + { + /* Root may set any value; non-root may only set to real or saved. */ + + rgroup->tg_euid = uid; + } + else + { + set_errno(EPERM); + return ERROR; + } + return OK; } diff --git a/sched/group/group_setgid.c b/sched/group/group_setgid.c index 2fc0b423148..72131e5ee5f 100644 --- a/sched/group/group_setgid.c +++ b/sched/group/group_setgid.c @@ -79,9 +79,27 @@ int setgid(gid_t gid) rtcb = this_task(); rgroup = rtcb->group; - /* Set the task group's group identity. */ - DEBUGASSERT(rgroup != NULL); - rgroup->tg_gid = gid; + + if (rgroup->tg_egid == 0) + { + /* Root: set real, effective, and saved set-group-ID. */ + + rgroup->tg_gid = gid; + rgroup->tg_egid = gid; + rgroup->tg_sgid = gid; + } + else if (gid == rgroup->tg_gid || gid == rgroup->tg_sgid) + { + /* Non-root: may only set effective GID to real or saved value. */ + + rgroup->tg_egid = gid; + } + else + { + set_errno(EPERM); + return ERROR; + } + return OK; } diff --git a/sched/group/group_setuid.c b/sched/group/group_setuid.c index 46cf4f8b16f..16073ed5313 100644 --- a/sched/group/group_setuid.c +++ b/sched/group/group_setuid.c @@ -80,9 +80,27 @@ int setuid(uid_t uid) rtcb = this_task(); rgroup = rtcb->group; - /* Set the task group's group identity. */ - DEBUGASSERT(rgroup != NULL); - rgroup->tg_uid = uid; + + if (rgroup->tg_euid == 0) + { + /* Root: set real, effective, and saved set-user-ID. */ + + rgroup->tg_uid = uid; + rgroup->tg_euid = uid; + rgroup->tg_suid = uid; + } + else if (uid == rgroup->tg_uid || uid == rgroup->tg_suid) + { + /* Non-root: may only set effective UID to real or saved value. */ + + rgroup->tg_euid = uid; + } + else + { + set_errno(EPERM); + return ERROR; + } + return OK; }
