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"

Reply via email to