From 4c622716543635a5987ab19cc8d7229af4210e8b Mon Sep 17 00:00:00 2001 From: Abhishek Mishra Date: Thu, 16 Jul 2026 18:55:10 +0000 Subject: [PATCH] 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 --- include/sys/syscall_lookup.h | 4 + include/unistd.h | 3 + libs/libc/unistd/CMakeLists.txt | 8 +- libs/libc/unistd/Make.defs | 3 +- libs/libc/unistd/lib_getresgid.c | 73 +++++++++++++++ libs/libc/unistd/lib_getresuid.c | 73 +++++++++++++++ libs/libc/unistd/lib_setregid.c | 27 ++---- libs/libc/unistd/lib_setreuid.c | 26 ++---- sched/group/CMakeLists.txt | 6 +- sched/group/Make.defs | 1 + sched/group/group_getresgid.c | 79 ++++++++++++++++ sched/group/group_getresuid.c | 79 ++++++++++++++++ sched/group/group_setregid.c | 154 ++++++++++++++++++++++++++++++ sched/group/group_setreuid.c | 155 +++++++++++++++++++++++++++++++ syscall/syscall.csv | 4 + 15 files changed, 657 insertions(+), 38 deletions(-) create mode 100644 libs/libc/unistd/lib_getresgid.c create mode 100644 libs/libc/unistd/lib_getresuid.c create mode 100644 sched/group/group_getresgid.c create mode 100644 sched/group/group_getresuid.c create mode 100644 sched/group/group_setregid.c create mode 100644 sched/group/group_setreuid.c 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_getresgid.c b/libs/libc/unistd/lib_getresgid.c new file mode 100644 index 00000000000..6cddc19fdb1 --- /dev/null +++ b/libs/libc/unistd/lib_getresgid.c @@ -0,0 +1,73 @@ +/**************************************************************************** + * libs/libc/unistd/lib_getresgid.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getresgid + * + * Description: + * The getresgid() function gets the real, effective, and saved set-group + * IDs of the calling process. + * + * Input Parameters: + * 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 + * appropriately. + * + ****************************************************************************/ + +int getresgid(FAR gid_t *rgid, FAR gid_t *egid, FAR gid_t *sgid) +{ + /* NuttX only supports the group identity 'root' with a gid value of 0. */ + + if (rgid != NULL) + { + *rgid = 0; + } + + if (egid != NULL) + { + *egid = 0; + } + + if (sgid != NULL) + { + *sgid = 0; + } + + return 0; +} diff --git a/libs/libc/unistd/lib_getresuid.c b/libs/libc/unistd/lib_getresuid.c new file mode 100644 index 00000000000..7621f0e3aa3 --- /dev/null +++ b/libs/libc/unistd/lib_getresuid.c @@ -0,0 +1,73 @@ +/**************************************************************************** + * libs/libc/unistd/lib_getresuid.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getresuid + * + * Description: + * The getresuid() function gets the real, effective, and saved set-user + * IDs of the calling process. + * + * Input Parameters: + * 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 + * appropriately. + * + ****************************************************************************/ + +int getresuid(FAR uid_t *ruid, FAR uid_t *euid, FAR uid_t *suid) +{ + /* NuttX only supports the user identity 'root' with a uid value of 0. */ + + if (ruid != NULL) + { + *ruid = 0; + } + + if (euid != NULL) + { + *euid = 0; + } + + if (suid != NULL) + { + *suid = 0; + } + + 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 */ + /* All other gid values are considered invalid and not supported by the + * implementation. + */ - ret = setegid(egid); - } - - 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 */ + /* All other uid values are considered invalid and not supported by the + * implementation. + */ - ret = seteuid(euid); - } - - 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/sched/group/group_getresgid.c b/sched/group/group_getresgid.c new file mode 100644 index 00000000000..92db2e1e0e2 --- /dev/null +++ b/sched/group/group_getresgid.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * sched/group/group_getresgid.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getresgid + * + * Description: + * The getresgid() function gets the real, effective, and saved set-group + * IDs of the calling process. + * + * Input Parameters: + * 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 + * appropriately. + * + ****************************************************************************/ + +int getresgid(FAR gid_t *rgid, FAR gid_t *egid, FAR gid_t *sgid) +{ + FAR struct tcb_s *rtcb = this_task(); + FAR struct task_group_s *rgroup = rtcb->group; + + DEBUGASSERT(rgroup != NULL); + + if (rgid != NULL) + { + *rgid = rgroup->tg_gid; + } + + if (egid != NULL) + { + *egid = rgroup->tg_egid; + } + + if (sgid != NULL) + { + *sgid = rgroup->tg_sgid; + } + + return OK; +} diff --git a/sched/group/group_getresuid.c b/sched/group/group_getresuid.c new file mode 100644 index 00000000000..cd247b74db4 --- /dev/null +++ b/sched/group/group_getresuid.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * sched/group/group_getresuid.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getresuid + * + * Description: + * The getresuid() function gets the real, effective, and saved set-user + * IDs of the calling process. + * + * Input Parameters: + * 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 + * appropriately. + * + ****************************************************************************/ + +int getresuid(FAR uid_t *ruid, FAR uid_t *euid, FAR uid_t *suid) +{ + FAR struct tcb_s *rtcb = this_task(); + FAR struct task_group_s *rgroup = rtcb->group; + + DEBUGASSERT(rgroup != NULL); + + if (ruid != NULL) + { + *ruid = rgroup->tg_uid; + } + + if (euid != NULL) + { + *euid = rgroup->tg_euid; + } + + if (suid != NULL) + { + *suid = rgroup->tg_suid; + } + + return OK; +} diff --git a/sched/group/group_setregid.c b/sched/group/group_setregid.c new file mode 100644 index 00000000000..61360f939dd --- /dev/null +++ b/sched/group/group_setregid.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * sched/group/group_setregid.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setregid + * + * Description: + * The setregid() function sets the real group ID and/or the effective + * 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. + * egid - Effective group identity to set. The special value (gid_t)-1 + * indicates that the effective group ID should not be changed. + * + * Returned Value: + * Zero if successful and -1 in case of failure, in which case errno is set + * appropriately. + * + ****************************************************************************/ + +int setregid(gid_t rgid, gid_t egid) +{ + 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 && (uint16_t)rgid > INT16_MAX) + { + set_errno(EINVAL); + return ERROR; + } + + if (egid != (gid_t)-1 && (uint16_t)egid > INT16_MAX) + { + set_errno(EINVAL); + return ERROR; + } + + if (rgid == (gid_t)-1 && egid == (gid_t)-1) + { + return OK; + } + + 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) + { + /* 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 */ + + 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 OK; +} diff --git a/sched/group/group_setreuid.c b/sched/group/group_setreuid.c new file mode 100644 index 00000000000..0610f9fdda6 --- /dev/null +++ b/sched/group/group_setreuid.c @@ -0,0 +1,155 @@ +/**************************************************************************** + * sched/group/group_setreuid.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setreuid + * + * Description: + * The setreuid() function sets the real user ID and/or the effective user + * 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. + * euid - Effective user identity to set. The special value (uid_t)-1 + * indicates that the effective user ID should not be changed. + * + * Returned Value: + * Zero if successful and -1 in case of failure, in which case errno is set + * appropriately. + * + ****************************************************************************/ + +int setreuid(uid_t ruid, uid_t euid) +{ + 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 && (uint16_t)ruid > INT16_MAX) + { + set_errno(EINVAL); + return ERROR; + } + + if (euid != (uid_t)-1 && (uint16_t)euid > INT16_MAX) + { + set_errno(EINVAL); + return ERROR; + } + + if (ruid == (uid_t)-1 && euid == (uid_t)-1) + { + return OK; + } + + 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) + { + /* 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 */ + + 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 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"