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 <mishra.abhishek2808@gmail.com>
This commit is contained in:
Abhishek Mishra 2026-06-10 08:03:35 +00:00 committed by Xiang Xiao
parent f442c6b05e
commit 14661fdba0
6 changed files with 76 additions and 14 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}