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 4c622716543635a5987ab19cc8d7229af4210e8b Author: Abhishek Mishra <[email protected]> AuthorDate: Thu Jul 16 18:55:10 2026 +0000 sched/group: add getresuid, getresgid, setreuid, and setregid Implement POSIX real/effective/saved credential getters and paired setters in the task group layer, with libc stubs and syscalls. Signed-off-by: Abhishek Mishra <[email protected]> --- include/sys/syscall_lookup.h | 4 + include/unistd.h | 3 + libs/libc/unistd/CMakeLists.txt | 8 +- libs/libc/unistd/Make.defs | 3 +- .../unistd/{lib_setreuid.c => lib_getresgid.c} | 40 ++++---- .../unistd/{lib_setreuid.c => lib_getresuid.c} | 40 ++++---- libs/libc/unistd/lib_setregid.c | 27 ++---- libs/libc/unistd/lib_setreuid.c | 26 ++--- sched/group/CMakeLists.txt | 6 +- sched/group/Make.defs | 1 + .../group/group_getresgid.c | 46 ++++----- .../group/group_getresuid.c | 46 ++++----- .../lib_setregid.c => sched/group/group_setregid.c | 106 ++++++++++++++++++--- .../lib_setreuid.c => sched/group/group_setreuid.c | 106 ++++++++++++++++++--- syscall/syscall.csv | 4 + 15 files changed, 311 insertions(+), 155 deletions(-) diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 7a1f37284c8..97b1cee5b05 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -71,6 +71,10 @@ SYSCALL_LOOKUP(sethostname, 2) SYSCALL_LOOKUP(geteuid, 0) SYSCALL_LOOKUP(setegid, 1) SYSCALL_LOOKUP(getegid, 0) + SYSCALL_LOOKUP(setreuid, 2) + SYSCALL_LOOKUP(setregid, 2) + SYSCALL_LOOKUP(getresuid, 3) + SYSCALL_LOOKUP(getresgid, 3) #endif /* Semaphores */ diff --git a/include/unistd.h b/include/unistd.h index 63ded5444ac..e9d1686248c 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -494,6 +494,9 @@ gid_t getegid(void); int setreuid(uid_t ruid, uid_t euid); int setregid(gid_t rgid, gid_t egid); +int getresuid(FAR uid_t *ruid, FAR uid_t *euid, FAR uid_t *suid); +int getresgid(FAR gid_t *rgid, FAR gid_t *egid, FAR gid_t *sgid); + int getgroups(int, gid_t[]); int getentropy(FAR void *buffer, size_t length); diff --git a/libs/libc/unistd/CMakeLists.txt b/libs/libc/unistd/CMakeLists.txt index eb4ca8e5e93..3521d45f607 100644 --- a/libs/libc/unistd/CMakeLists.txt +++ b/libs/libc/unistd/CMakeLists.txt @@ -43,8 +43,6 @@ set(SRCS lib_statvfs.c lib_sleep.c lib_nice.c - lib_setreuid.c - lib_setregid.c lib_getrusage.c lib_utime.c lib_utimes.c @@ -87,7 +85,11 @@ if(NOT CONFIG_SCHED_USER_IDENTITY) lib_seteuid.c lib_setegid.c lib_geteuid.c - lib_getegid.c) + lib_getegid.c + lib_setreuid.c + lib_setregid.c + lib_getresuid.c + lib_getresgid.c) endif() if(NOT CONFIG_DISABLE_ENVIRON) diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs index e3e5ed3a214..602887be4c3 100644 --- a/libs/libc/unistd/Make.defs +++ b/libs/libc/unistd/Make.defs @@ -27,7 +27,7 @@ CSRCS += lib_getcwd.c lib_getentropy.c lib_getopt_common.c lib_getopt.c CSRCS += lib_getopt_long.c lib_getopt_longonly.c lib_getoptvars.c lib_getoptargp.c CSRCS += lib_getopterrp.c lib_getoptindp.c lib_getoptoptp.c lib_times.c CSRCS += lib_alarm.c lib_fstatvfs.c lib_statvfs.c lib_sleep.c lib_nice.c -CSRCS += lib_setreuid.c lib_setregid.c lib_getrusage.c lib_utime.c lib_utimes.c +CSRCS += lib_getrusage.c lib_utime.c lib_utimes.c CSRCS += lib_setrlimit.c lib_getrlimit.c lib_setpriority.c lib_getpriority.c CSRCS += lib_futimes.c lib_lutimes.c lib_gethostname.c lib_sethostname.c CSRCS += lib_fchownat.c lib_linkat.c lib_readlinkat.c lib_symlinkat.c @@ -39,6 +39,7 @@ CSRCS += lib_chdir.c lib_fchdir.c lib_confstr.c lib_ulimit.c ifneq ($(CONFIG_SCHED_USER_IDENTITY),y) CSRCS += lib_setuid.c lib_setgid.c lib_getuid.c lib_getgid.c CSRCS += lib_seteuid.c lib_setegid.c lib_geteuid.c lib_getegid.c +CSRCS += lib_setreuid.c lib_setregid.c lib_getresuid.c lib_getresgid.c endif ifneq ($(CONFIG_DISABLE_ENVIRON),y) diff --git a/libs/libc/unistd/lib_setreuid.c b/libs/libc/unistd/lib_getresgid.c similarity index 65% copy from libs/libc/unistd/lib_setreuid.c copy to libs/libc/unistd/lib_getresgid.c index f2163a846fe..6cddc19fdb1 100644 --- a/libs/libc/unistd/lib_setreuid.c +++ b/libs/libc/unistd/lib_getresgid.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/unistd/lib_setreuid.c + * libs/libc/unistd/lib_getresgid.c * * SPDX-License-Identifier: Apache-2.0 * @@ -27,24 +27,22 @@ #include <nuttx/config.h> #include <unistd.h> -#include <errno.h> /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: setreuid + * Name: getresgid * * Description: - * The setreuid() function sets the real user ID and/or the effective user - * ID of the calling task group to ruid and/or euid. + * The getresgid() function gets the real, effective, and saved set-group + * IDs of the calling process. * * Input Parameters: - * ruid - Real user identity to set. The special value (uid_t)-1 - * indicates that the real user ID should not be changed. - * ruid - Effective user identity to set. The special value (uid_t)-1 - * indicates that the effective user ID should not be changed. + * rgid - Location to return the real group ID, or NULL. + * egid - Location to return the effective group ID, or NULL. + * sgid - Location to return the saved set-group ID, or NULL. * * Returned Value: * Zero if successful and -1 in case of failure, in which case errno is set @@ -52,26 +50,24 @@ * ****************************************************************************/ -int setreuid(uid_t ruid, uid_t euid) +int getresgid(FAR gid_t *rgid, FAR gid_t *egid, FAR gid_t *sgid) { - int ret = OK; + /* NuttX only supports the group identity 'root' with a gid value of 0. */ - if (ruid != (uid_t)-1) + if (rgid != NULL) { - /* Set the real user ID. CAREFUL: This exploits non-standard behavior - * of setuid(): setuid() should set the real, effective, and saved - * user ID. Here we depend on it setting only the real user ID. - */ - - ret = setuid(ruid); + *rgid = 0; } - if (ret >= 0 && euid != (uid_t)-1) + if (egid != NULL) { - /* Set the effective user ID */ + *egid = 0; + } - ret = seteuid(euid); + if (sgid != NULL) + { + *sgid = 0; } - return ret; + return 0; } diff --git a/libs/libc/unistd/lib_setreuid.c b/libs/libc/unistd/lib_getresuid.c similarity index 65% copy from libs/libc/unistd/lib_setreuid.c copy to libs/libc/unistd/lib_getresuid.c index f2163a846fe..7621f0e3aa3 100644 --- a/libs/libc/unistd/lib_setreuid.c +++ b/libs/libc/unistd/lib_getresuid.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/unistd/lib_setreuid.c + * libs/libc/unistd/lib_getresuid.c * * SPDX-License-Identifier: Apache-2.0 * @@ -27,24 +27,22 @@ #include <nuttx/config.h> #include <unistd.h> -#include <errno.h> /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: setreuid + * Name: getresuid * * Description: - * The setreuid() function sets the real user ID and/or the effective user - * ID of the calling task group to ruid and/or euid. + * The getresuid() function gets the real, effective, and saved set-user + * IDs of the calling process. * * Input Parameters: - * ruid - Real user identity to set. The special value (uid_t)-1 - * indicates that the real user ID should not be changed. - * ruid - Effective user identity to set. The special value (uid_t)-1 - * indicates that the effective user ID should not be changed. + * ruid - Location to return the real user ID, or NULL. + * euid - Location to return the effective user ID, or NULL. + * suid - Location to return the saved set-user ID, or NULL. * * Returned Value: * Zero if successful and -1 in case of failure, in which case errno is set @@ -52,26 +50,24 @@ * ****************************************************************************/ -int setreuid(uid_t ruid, uid_t euid) +int getresuid(FAR uid_t *ruid, FAR uid_t *euid, FAR uid_t *suid) { - int ret = OK; + /* NuttX only supports the user identity 'root' with a uid value of 0. */ - if (ruid != (uid_t)-1) + if (ruid != NULL) { - /* Set the real user ID. CAREFUL: This exploits non-standard behavior - * of setuid(): setuid() should set the real, effective, and saved - * user ID. Here we depend on it setting only the real user ID. - */ - - ret = setuid(ruid); + *ruid = 0; } - if (ret >= 0 && euid != (uid_t)-1) + if (euid != NULL) { - /* Set the effective user ID */ + *euid = 0; + } - ret = seteuid(euid); + if (suid != NULL) + { + *suid = 0; } - return ret; + return 0; } diff --git a/libs/libc/unistd/lib_setregid.c b/libs/libc/unistd/lib_setregid.c index 0f331e97940..40cb19c8a49 100644 --- a/libs/libc/unistd/lib_setregid.c +++ b/libs/libc/unistd/lib_setregid.c @@ -43,7 +43,7 @@ * Input Parameters: * rgid - Real group identity to set. The special value (gid_t)-1 * indicates that the real group ID should not be changed. - * rgid - Effective group identity to set. The special value (gid_t)-1 + * egid - Effective group identity to set. The special value (gid_t)-1 * indicates that the effective group ID should not be changed. * * Returned Value: @@ -54,25 +54,18 @@ int setregid(gid_t rgid, gid_t egid) { - int ret = OK; + /* NuttX only supports the group identity 'root' with a gid value of 0. */ - if (rgid != (gid_t)-1) + if ((rgid == (gid_t)-1 || rgid == 0) && + (egid == (gid_t)-1 || egid == 0)) { - /* Set the real group ID. CAREFUL: This exploits non-standard - * behavior of setgid(): setgid() should set the real, effective, and - * saved group ID. Here we depend on it setting only the real group - * ID. - */ - - ret = setgid(rgid); + return 0; } - if (ret >= 0 && egid != (gid_t)-1) - { - /* Set the effective group ID */ - - ret = setegid(egid); - } + /* All other gid values are considered invalid and not supported by the + * implementation. + */ - return ret; + set_errno(EINVAL); + return -1; } diff --git a/libs/libc/unistd/lib_setreuid.c b/libs/libc/unistd/lib_setreuid.c index f2163a846fe..bd8f439f426 100644 --- a/libs/libc/unistd/lib_setreuid.c +++ b/libs/libc/unistd/lib_setreuid.c @@ -43,7 +43,7 @@ * Input Parameters: * ruid - Real user identity to set. The special value (uid_t)-1 * indicates that the real user ID should not be changed. - * ruid - Effective user identity to set. The special value (uid_t)-1 + * euid - Effective user identity to set. The special value (uid_t)-1 * indicates that the effective user ID should not be changed. * * Returned Value: @@ -54,24 +54,18 @@ int setreuid(uid_t ruid, uid_t euid) { - int ret = OK; + /* NuttX only supports the user identity 'root' with a uid value of 0. */ - if (ruid != (uid_t)-1) + if ((ruid == (uid_t)-1 || ruid == 0) && + (euid == (uid_t)-1 || euid == 0)) { - /* Set the real user ID. CAREFUL: This exploits non-standard behavior - * of setuid(): setuid() should set the real, effective, and saved - * user ID. Here we depend on it setting only the real user ID. - */ - - ret = setuid(ruid); + return 0; } - if (ret >= 0 && euid != (uid_t)-1) - { - /* Set the effective user ID */ - - ret = seteuid(euid); - } + /* All other uid values are considered invalid and not supported by the + * implementation. + */ - return ret; + set_errno(EINVAL); + return -1; } diff --git a/sched/group/CMakeLists.txt b/sched/group/CMakeLists.txt index dcb96d6952d..736b50dcd58 100644 --- a/sched/group/CMakeLists.txt +++ b/sched/group/CMakeLists.txt @@ -52,7 +52,11 @@ if(CONFIG_SCHED_USER_IDENTITY) group_seteuid.c group_setegid.c group_geteuid.c - group_getegid.c) + group_getegid.c + group_setreuid.c + group_setregid.c + group_getresuid.c + group_getresgid.c) endif() if(CONFIG_SIG_SIGSTOP_ACTION) diff --git a/sched/group/Make.defs b/sched/group/Make.defs index 98ea6d09c6f..3b822fbf2f5 100644 --- a/sched/group/Make.defs +++ b/sched/group/Make.defs @@ -41,6 +41,7 @@ endif ifeq ($(CONFIG_SCHED_USER_IDENTITY),y) CSRCS += group_setuid.c group_setgid.c group_getuid.c group_getgid.c CSRCS += group_seteuid.c group_setegid.c group_geteuid.c group_getegid.c +CSRCS += group_setreuid.c group_setregid.c group_getresuid.c group_getresgid.c endif ifeq ($(CONFIG_SIG_SIGSTOP_ACTION),y) diff --git a/libs/libc/unistd/lib_setreuid.c b/sched/group/group_getresgid.c similarity index 65% copy from libs/libc/unistd/lib_setreuid.c copy to sched/group/group_getresgid.c index f2163a846fe..92db2e1e0e2 100644 --- a/libs/libc/unistd/lib_setreuid.c +++ b/sched/group/group_getresgid.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/unistd/lib_setreuid.c + * sched/group/group_getresgid.c * * SPDX-License-Identifier: Apache-2.0 * @@ -27,24 +27,25 @@ #include <nuttx/config.h> #include <unistd.h> -#include <errno.h> +#include <assert.h> + +#include <sched/sched.h> /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: setreuid + * Name: getresgid * * Description: - * The setreuid() function sets the real user ID and/or the effective user - * ID of the calling task group to ruid and/or euid. + * The getresgid() function gets the real, effective, and saved set-group + * IDs of the calling process. * * Input Parameters: - * ruid - Real user identity to set. The special value (uid_t)-1 - * indicates that the real user ID should not be changed. - * ruid - Effective user identity to set. The special value (uid_t)-1 - * indicates that the effective user ID should not be changed. + * rgid - Location to return the real group ID, or NULL. + * egid - Location to return the effective group ID, or NULL. + * sgid - Location to return the saved set-group ID, or NULL. * * Returned Value: * Zero if successful and -1 in case of failure, in which case errno is set @@ -52,26 +53,27 @@ * ****************************************************************************/ -int setreuid(uid_t ruid, uid_t euid) +int getresgid(FAR gid_t *rgid, FAR gid_t *egid, FAR gid_t *sgid) { - int ret = OK; + FAR struct tcb_s *rtcb = this_task(); + FAR struct task_group_s *rgroup = rtcb->group; - if (ruid != (uid_t)-1) - { - /* Set the real user ID. CAREFUL: This exploits non-standard behavior - * of setuid(): setuid() should set the real, effective, and saved - * user ID. Here we depend on it setting only the real user ID. - */ + DEBUGASSERT(rgroup != NULL); - ret = setuid(ruid); + if (rgid != NULL) + { + *rgid = rgroup->tg_gid; } - if (ret >= 0 && euid != (uid_t)-1) + if (egid != NULL) { - /* Set the effective user ID */ + *egid = rgroup->tg_egid; + } - ret = seteuid(euid); + if (sgid != NULL) + { + *sgid = rgroup->tg_sgid; } - return ret; + return OK; } diff --git a/libs/libc/unistd/lib_setreuid.c b/sched/group/group_getresuid.c similarity index 65% copy from libs/libc/unistd/lib_setreuid.c copy to sched/group/group_getresuid.c index f2163a846fe..cd247b74db4 100644 --- a/libs/libc/unistd/lib_setreuid.c +++ b/sched/group/group_getresuid.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/unistd/lib_setreuid.c + * sched/group/group_getresuid.c * * SPDX-License-Identifier: Apache-2.0 * @@ -27,24 +27,25 @@ #include <nuttx/config.h> #include <unistd.h> -#include <errno.h> +#include <assert.h> + +#include <sched/sched.h> /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: setreuid + * Name: getresuid * * Description: - * The setreuid() function sets the real user ID and/or the effective user - * ID of the calling task group to ruid and/or euid. + * The getresuid() function gets the real, effective, and saved set-user + * IDs of the calling process. * * Input Parameters: - * ruid - Real user identity to set. The special value (uid_t)-1 - * indicates that the real user ID should not be changed. - * ruid - Effective user identity to set. The special value (uid_t)-1 - * indicates that the effective user ID should not be changed. + * ruid - Location to return the real user ID, or NULL. + * euid - Location to return the effective user ID, or NULL. + * suid - Location to return the saved set-user ID, or NULL. * * Returned Value: * Zero if successful and -1 in case of failure, in which case errno is set @@ -52,26 +53,27 @@ * ****************************************************************************/ -int setreuid(uid_t ruid, uid_t euid) +int getresuid(FAR uid_t *ruid, FAR uid_t *euid, FAR uid_t *suid) { - int ret = OK; + FAR struct tcb_s *rtcb = this_task(); + FAR struct task_group_s *rgroup = rtcb->group; - if (ruid != (uid_t)-1) - { - /* Set the real user ID. CAREFUL: This exploits non-standard behavior - * of setuid(): setuid() should set the real, effective, and saved - * user ID. Here we depend on it setting only the real user ID. - */ + DEBUGASSERT(rgroup != NULL); - ret = setuid(ruid); + if (ruid != NULL) + { + *ruid = rgroup->tg_uid; } - if (ret >= 0 && euid != (uid_t)-1) + if (euid != NULL) { - /* Set the effective user ID */ + *euid = rgroup->tg_euid; + } - ret = seteuid(euid); + if (suid != NULL) + { + *suid = rgroup->tg_suid; } - return ret; + return OK; } diff --git a/libs/libc/unistd/lib_setregid.c b/sched/group/group_setregid.c similarity index 51% copy from libs/libc/unistd/lib_setregid.c copy to sched/group/group_setregid.c index 0f331e97940..61360f939dd 100644 --- a/libs/libc/unistd/lib_setregid.c +++ b/sched/group/group_setregid.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/unistd/lib_setregid.c + * sched/group/group_setregid.c * * SPDX-License-Identifier: Apache-2.0 * @@ -27,8 +27,11 @@ #include <nuttx/config.h> #include <unistd.h> +#include <assert.h> #include <errno.h> +#include <sched/sched.h> + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -38,12 +41,12 @@ * * Description: * The setregid() function sets the real group ID and/or the effective - * group ID of the calling task group to rgid and/or egid. + * group ID of the calling process. * * Input Parameters: * rgid - Real group identity to set. The special value (gid_t)-1 * indicates that the real group ID should not be changed. - * rgid - Effective group identity to set. The special value (gid_t)-1 + * egid - Effective group identity to set. The special value (gid_t)-1 * indicates that the effective group ID should not be changed. * * Returned Value: @@ -54,25 +57,98 @@ int setregid(gid_t rgid, gid_t egid) { - int ret = OK; + FAR struct tcb_s *rtcb; + FAR struct task_group_s *rgroup; + gid_t old_rgid; + gid_t old_egid; + gid_t old_sgid; - if (rgid != (gid_t)-1) + if (rgid != (gid_t)-1 && (uint16_t)rgid > INT16_MAX) + { + set_errno(EINVAL); + return ERROR; + } + + if (egid != (gid_t)-1 && (uint16_t)egid > INT16_MAX) { - /* Set the real group ID. CAREFUL: This exploits non-standard - * behavior of setgid(): setgid() should set the real, effective, and - * saved group ID. Here we depend on it setting only the real group - * ID. - */ + set_errno(EINVAL); + return ERROR; + } - ret = setgid(rgid); + if (rgid == (gid_t)-1 && egid == (gid_t)-1) + { + return OK; } - if (ret >= 0 && egid != (gid_t)-1) + rtcb = this_task(); + rgroup = rtcb->group; + + DEBUGASSERT(rgroup != NULL); + + old_rgid = rgroup->tg_gid; + old_egid = rgroup->tg_egid; + old_sgid = rgroup->tg_sgid; + + if (old_egid == 0) { - /* Set the effective group ID */ + /* Super-user: may set any combination of real and effective IDs. */ + + if (rgid != (gid_t)-1) + { + rgroup->tg_gid = rgid; + + if (egid == (gid_t)-1) + { + rgroup->tg_egid = rgid; + rgroup->tg_sgid = rgid; + } + } + + if (egid != (gid_t)-1) + { + rgroup->tg_egid = egid; + rgroup->tg_sgid = egid; + } + + return OK; + } + + /* Non-super-user */ - ret = setegid(egid); + if (rgid != (gid_t)-1 && + rgid != old_egid && rgid != old_sgid) + { + set_errno(EPERM); + return ERROR; + } + + if (egid != (gid_t)-1 && + egid != old_egid && egid != old_sgid && egid != old_rgid) + { + set_errno(EPERM); + return ERROR; + } + + if (rgid != (gid_t)-1) + { + rgroup->tg_gid = rgid; + } + + if (egid != (gid_t)-1) + { + rgroup->tg_egid = egid; + } + + /* If the real group ID is being set, or the effective group ID is being + * changed to a value not equal to the real group ID, update the saved + * set-group-ID to the new effective group ID. + */ + + if ((rgid != (gid_t)-1 && rgroup->tg_gid != old_rgid) || + (egid != (gid_t)-1 && rgroup->tg_egid != old_rgid)) + { + rgroup->tg_sgid = rgroup->tg_egid; } - return ret; + return OK; } diff --git a/libs/libc/unistd/lib_setreuid.c b/sched/group/group_setreuid.c similarity index 51% copy from libs/libc/unistd/lib_setreuid.c copy to sched/group/group_setreuid.c index f2163a846fe..0610f9fdda6 100644 --- a/libs/libc/unistd/lib_setreuid.c +++ b/sched/group/group_setreuid.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/unistd/lib_setreuid.c + * sched/group/group_setreuid.c * * SPDX-License-Identifier: Apache-2.0 * @@ -26,9 +26,13 @@ #include <nuttx/config.h> +#include <sys/types.h> #include <unistd.h> +#include <assert.h> #include <errno.h> +#include <sched/sched.h> + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -38,12 +42,12 @@ * * Description: * The setreuid() function sets the real user ID and/or the effective user - * ID of the calling task group to ruid and/or euid. + * ID of the calling process. * * Input Parameters: * ruid - Real user identity to set. The special value (uid_t)-1 * indicates that the real user ID should not be changed. - * ruid - Effective user identity to set. The special value (uid_t)-1 + * euid - Effective user identity to set. The special value (uid_t)-1 * indicates that the effective user ID should not be changed. * * Returned Value: @@ -54,24 +58,98 @@ int setreuid(uid_t ruid, uid_t euid) { - int ret = OK; + FAR struct tcb_s *rtcb; + FAR struct task_group_s *rgroup; + uid_t old_ruid; + uid_t old_euid; + uid_t old_suid; - if (ruid != (uid_t)-1) + if (ruid != (uid_t)-1 && (uint16_t)ruid > INT16_MAX) + { + set_errno(EINVAL); + return ERROR; + } + + if (euid != (uid_t)-1 && (uint16_t)euid > INT16_MAX) { - /* Set the real user ID. CAREFUL: This exploits non-standard behavior - * of setuid(): setuid() should set the real, effective, and saved - * user ID. Here we depend on it setting only the real user ID. - */ + set_errno(EINVAL); + return ERROR; + } - ret = setuid(ruid); + if (ruid == (uid_t)-1 && euid == (uid_t)-1) + { + return OK; } - if (ret >= 0 && euid != (uid_t)-1) + rtcb = this_task(); + rgroup = rtcb->group; + + DEBUGASSERT(rgroup != NULL); + + old_ruid = rgroup->tg_uid; + old_euid = rgroup->tg_euid; + old_suid = rgroup->tg_suid; + + if (old_euid == 0) { - /* Set the effective user ID */ + /* Super-user: may set any combination of real and effective IDs. */ + + if (ruid != (uid_t)-1) + { + rgroup->tg_uid = ruid; + + if (euid == (uid_t)-1) + { + rgroup->tg_euid = ruid; + rgroup->tg_suid = ruid; + } + } + + if (euid != (uid_t)-1) + { + rgroup->tg_euid = euid; + rgroup->tg_suid = euid; + } + + return OK; + } + + /* Non-super-user */ - ret = seteuid(euid); + if (ruid != (uid_t)-1 && + ruid != old_euid && ruid != old_suid) + { + set_errno(EPERM); + return ERROR; + } + + if (euid != (uid_t)-1 && + euid != old_euid && euid != old_suid && euid != old_ruid) + { + set_errno(EPERM); + return ERROR; + } + + if (ruid != (uid_t)-1) + { + rgroup->tg_uid = ruid; + } + + if (euid != (uid_t)-1) + { + rgroup->tg_euid = euid; + } + + /* If the real user ID is being set, or the effective user ID is being + * changed to a value not equal to the real user ID, update the saved + * set-user-ID to the new effective user ID. + */ + + if ((ruid != (uid_t)-1 && rgroup->tg_uid != old_ruid) || + (euid != (uid_t)-1 && rgroup->tg_euid != old_ruid)) + { + rgroup->tg_suid = rgroup->tg_euid; } - return ret; + return OK; } diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 4622a0910b8..582deb3907f 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -39,6 +39,8 @@ "futimens","sys/stat.h","","int","int","const struct timespec [2]|FAR const struct timespec *" "get_environ_ptr","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","FAR char **" "getegid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","gid_t" +"getresgid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","gid_t *","gid_t *","gid_t *" +"getresuid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","uid_t *","uid_t *","uid_t *" "getenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","FAR char *","FAR const char *" "geteuid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","uid_t" "getgid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","gid_t" @@ -150,6 +152,8 @@ "sendmsg","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR const struct msghdr *","int" "sendto","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR const void *","size_t","int","FAR const struct sockaddr *","socklen_t" "setegid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","gid_t" +"setregid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","gid_t","gid_t" +"setreuid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","uid_t","uid_t" "setenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char *","FAR const char *","int" "seteuid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","uid_t" "setgid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","gid_t"
