[libc-commits] [libc] [libc] Implement setresuid and setresgid in unistd (PR #234837)

Aman Maurya via libc-commits libc-commits at lists.llvm.org
Fri Oct 23 01:00:25 PDT 2026


https://github.com/amanmaurya92 updated https://github.com/llvm/llvm-project/pull/234837

>From 77c46af1cce6674b772ed17f34edbd4626a54754 Mon Sep 17 00:00:00 2001
From: amanmaurya92 <amanmaurya9209 at gmail.com>
Date: Fri, 23 Oct 2026 09:36:02 +0530
Subject: [PATCH 1/2] [libc] Implement setresuid and setresgid in unistd

Implement the POSIX/Linux standard functions setresuid and setresgid in <unistd.h>.
- Call existing setresuid and setresgid linux syscall wrappers.
- Add entrypoints under experimental on Linux targets (aarch64, arm, riscv, x86_64).
- Add TODO comments regarding setxid thread propagation.
- Add unit tests covering noop (-1), current IDs, and unprivileged invalid IDs.

Fixes #234694.
---
 libc/config/linux/aarch64/entrypoints.txt |  2 +
 libc/config/linux/arm/entrypoints.txt     |  2 +
 libc/config/linux/riscv/entrypoints.txt   |  2 +
 libc/config/linux/x86_64/entrypoints.txt  |  2 +
 libc/include/unistd.yaml                  | 16 ++++++++
 libc/src/unistd/CMakeLists.txt            | 14 +++++++
 libc/src/unistd/linux/CMakeLists.txt      | 24 ++++++++++++
 libc/src/unistd/linux/setresgid.cpp       | 34 ++++++++++++++++
 libc/src/unistd/linux/setresuid.cpp       | 34 ++++++++++++++++
 libc/src/unistd/setresgid.h               | 26 ++++++++++++
 libc/src/unistd/setresuid.h               | 26 ++++++++++++
 libc/test/src/unistd/CMakeLists.txt       | 30 ++++++++++++++
 libc/test/src/unistd/setresgid_test.cpp   | 48 +++++++++++++++++++++++
 libc/test/src/unistd/setresuid_test.cpp   | 48 +++++++++++++++++++++++
 14 files changed, 308 insertions(+)
 create mode 100644 libc/src/unistd/linux/setresgid.cpp
 create mode 100644 libc/src/unistd/linux/setresuid.cpp
 create mode 100644 libc/src/unistd/setresgid.h
 create mode 100644 libc/src/unistd/setresuid.h
 create mode 100644 libc/test/src/unistd/setresgid_test.cpp
 create mode 100644 libc/test/src/unistd/setresuid_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index be4d80db3afb3..243c06aecc687 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1551,7 +1551,9 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.unistd.seteuid
       libc.src.unistd.setgid
       libc.src.unistd.setregid
+      libc.src.unistd.setresgid
       libc.src.unistd.setreuid
+      libc.src.unistd.setresuid
       libc.src.unistd.setuid
 
       # wchar.h entrypoints
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 21488b488283b..6c37ece94a37b 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -756,7 +756,9 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.unistd.seteuid
       libc.src.unistd.setgid
       libc.src.unistd.setregid
+      libc.src.unistd.setresgid
       libc.src.unistd.setreuid
+      libc.src.unistd.setresuid
       libc.src.unistd.setuid
     )
   endif()
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 20e33295bfb20..b02bf6e4ca4a4 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1753,7 +1753,9 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.unistd.seteuid
       libc.src.unistd.setgid
       libc.src.unistd.setregid
+      libc.src.unistd.setresgid
       libc.src.unistd.setreuid
+      libc.src.unistd.setresuid
       libc.src.unistd.setuid
 
       # wchar.h entrypoints
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 7d7c3ad1e1768..336f26b0a9bca 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1789,7 +1789,9 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.unistd.seteuid
       libc.src.unistd.setgid
       libc.src.unistd.setregid
+      libc.src.unistd.setresgid
       libc.src.unistd.setreuid
+      libc.src.unistd.setresuid
       libc.src.unistd.setuid
 
       # wchar.h entrypoints
diff --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml
index 82d43ad5045f0..96ce15eee40b9 100644
--- a/libc/include/unistd.yaml
+++ b/libc/include/unistd.yaml
@@ -598,6 +598,14 @@ functions:
     arguments:
       - type: gid_t
       - type: gid_t
+  - name: setresgid
+    standards:
+      - linux
+    return_type: int
+    arguments:
+      - type: gid_t
+      - type: gid_t
+      - type: gid_t
   - name: setreuid
     standards:
       - posix
@@ -605,6 +613,14 @@ functions:
     arguments:
       - type: uid_t
       - type: uid_t
+  - name: setresuid
+    standards:
+      - linux
+    return_type: int
+    arguments:
+      - type: uid_t
+      - type: uid_t
+      - type: uid_t
   - name: setsid
     standards:
       - posix
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index 90690b725db17..0424641543d93 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -455,6 +455,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.setregid
 )
 
+add_entrypoint_object(
+  setresgid
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.setresgid
+)
+
 add_entrypoint_object(
   setreuid
   ALIAS
@@ -462,6 +469,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.setreuid
 )
 
+add_entrypoint_object(
+  setresuid
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.setresuid
+)
+
 add_entrypoint_object(
   setsid
   ALIAS
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index ad23e55630e75..f3a8d8f011ac9 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -843,6 +843,18 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  setresgid
+  SRCS
+    setresgid.cpp
+  HDRS
+    ../setresgid.h
+  DEPENDS
+    libc.hdr.types.gid_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.setresgid
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   setreuid
   SRCS
@@ -855,6 +867,18 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  setresuid
+  SRCS
+    setresuid.cpp
+  HDRS
+    ../setresuid.h
+  DEPENDS
+    libc.hdr.types.uid_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.setresuid
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   setsid
   SRCS
diff --git a/libc/src/unistd/linux/setresgid.cpp b/libc/src/unistd/linux/setresgid.cpp
new file mode 100644
index 0000000000000..2649977ff93da
--- /dev/null
+++ b/libc/src/unistd/linux/setresgid.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of setresgid.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/setresgid.h"
+
+#include "hdr/types/gid_t.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/setresgid.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, setresgid, (gid_t rgid, gid_t egid, gid_t sgid)) {
+  // TODO: Implement setxid propagation across threads.
+  auto ret = linux_syscalls::setresgid(rgid, egid, sgid);
+  if (!ret) {
+    libc_errno = ret.error();
+    return -1;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/linux/setresuid.cpp b/libc/src/unistd/linux/setresuid.cpp
new file mode 100644
index 0000000000000..04a4bbf602bc3
--- /dev/null
+++ b/libc/src/unistd/linux/setresuid.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of setresuid.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/setresuid.h"
+
+#include "hdr/types/uid_t.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/setresuid.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, setresuid, (uid_t ruid, uid_t euid, uid_t suid)) {
+  // TODO: Implement setxid propagation across threads.
+  auto ret = linux_syscalls::setresuid(ruid, euid, suid);
+  if (!ret) {
+    libc_errno = ret.error();
+    return -1;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/setresgid.h b/libc/src/unistd/setresgid.h
new file mode 100644
index 0000000000000..da5279cf3db12
--- /dev/null
+++ b/libc/src/unistd/setresgid.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for setresgid function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_SETRESGID_H
+#define LLVM_LIBC_SRC_UNISTD_SETRESGID_H
+
+#include "hdr/types/gid_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_SETRESGID_H
diff --git a/libc/src/unistd/setresuid.h b/libc/src/unistd/setresuid.h
new file mode 100644
index 0000000000000..41285897c65e5
--- /dev/null
+++ b/libc/src/unistd/setresuid.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for setresuid function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_SETRESUID_H
+#define LLVM_LIBC_SRC_UNISTD_SETRESUID_H
+
+#include "hdr/types/uid_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int setresuid(uid_t ruid, uid_t euid, uid_t suid);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_SETRESUID_H
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 251d0e4fc1703..abbe66fcf36d7 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -582,6 +582,21 @@ add_libc_test(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
+add_libc_test(
+  setresgid_test
+  SUITE
+    libc-unistd-tests
+  SRCS
+    setresgid_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.src.unistd.getegid
+    libc.src.unistd.getgid
+    libc.src.unistd.setresgid
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
 add_libc_test(
   setreuid_test
   SUITE
@@ -597,6 +612,21 @@ add_libc_test(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
+add_libc_test(
+  setresuid_test
+  SUITE
+    libc-unistd-tests
+  SRCS
+    setresuid_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.src.unistd.geteuid
+    libc.src.unistd.getuid
+    libc.src.unistd.setresuid
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
 add_libc_test(
   setsid_test
   SUITE
diff --git a/libc/test/src/unistd/setresgid_test.cpp b/libc/test/src/unistd/setresgid_test.cpp
new file mode 100644
index 0000000000000..903516153f986
--- /dev/null
+++ b/libc/test/src/unistd/setresgid_test.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unittests for setresgid.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "src/unistd/getegid.h"
+#include "src/unistd/getgid.h"
+#include "src/unistd/setresgid.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcSetResGidTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcSetResGidTest, NoopMinusOne) {
+  // Passing -1 leaves the corresponding ID unchanged and always succeeds.
+  ASSERT_THAT(LIBC_NAMESPACE::setresgid(static_cast<gid_t>(-1),
+                                        static_cast<gid_t>(-1),
+                                        static_cast<gid_t>(-1)),
+              Succeeds());
+}
+
+TEST_F(LlvmLibcSetResGidTest, SetCurrentResGid) {
+  // Setting the real and effective GIDs to their current values should succeed.
+  ASSERT_THAT(LIBC_NAMESPACE::setresgid(LIBC_NAMESPACE::getgid(),
+                                        LIBC_NAMESPACE::getegid(),
+                                        static_cast<gid_t>(-1)),
+              Succeeds());
+}
+
+TEST_F(LlvmLibcSetResGidTest, UnprivilegedInvalidGid) {
+  if (LIBC_NAMESPACE::getgid() == 0)
+    return;
+  ASSERT_THAT(LIBC_NAMESPACE::setresgid(static_cast<gid_t>(-2),
+                                        static_cast<gid_t>(-2),
+                                        static_cast<gid_t>(-2)),
+              Fails(any_of(EINVAL, EPERM)));
+}
diff --git a/libc/test/src/unistd/setresuid_test.cpp b/libc/test/src/unistd/setresuid_test.cpp
new file mode 100644
index 0000000000000..bea6eab882f26
--- /dev/null
+++ b/libc/test/src/unistd/setresuid_test.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unittests for setresuid.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "src/unistd/geteuid.h"
+#include "src/unistd/getuid.h"
+#include "src/unistd/setresuid.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcSetResUidTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcSetResUidTest, NoopMinusOne) {
+  // Passing -1 leaves the corresponding ID unchanged and always succeeds.
+  ASSERT_THAT(LIBC_NAMESPACE::setresuid(static_cast<uid_t>(-1),
+                                        static_cast<uid_t>(-1),
+                                        static_cast<uid_t>(-1)),
+              Succeeds());
+}
+
+TEST_F(LlvmLibcSetResUidTest, SetCurrentResUid) {
+  // Setting the real and effective UIDs to their current values should succeed.
+  ASSERT_THAT(LIBC_NAMESPACE::setresuid(LIBC_NAMESPACE::getuid(),
+                                        LIBC_NAMESPACE::geteuid(),
+                                        static_cast<uid_t>(-1)),
+              Succeeds());
+}
+
+TEST_F(LlvmLibcSetResUidTest, UnprivilegedInvalidUid) {
+  if (LIBC_NAMESPACE::getuid() == 0)
+    return;
+  ASSERT_THAT(LIBC_NAMESPACE::setresuid(static_cast<uid_t>(-2),
+                                        static_cast<uid_t>(-2),
+                                        static_cast<uid_t>(-2)),
+              Fails(any_of(EINVAL, EPERM)));
+}

>From 7f0ab7a503a21b3c318ba61aa229272c302bc3ea Mon Sep 17 00:00:00 2001
From: amanmaurya92 <amanmaurya9209 at gmail.com>
Date: Fri, 23 Oct 2026 13:30:00 +0530
Subject: [PATCH 2/2] [libc] Sort setresuid before setreuid in entrypoints

---
 libc/config/linux/aarch64/entrypoints.txt | 2 +-
 libc/config/linux/arm/entrypoints.txt     | 2 +-
 libc/config/linux/riscv/entrypoints.txt   | 2 +-
 libc/config/linux/x86_64/entrypoints.txt  | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 243c06aecc687..b914c63ec69a3 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1552,8 +1552,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.unistd.setgid
       libc.src.unistd.setregid
       libc.src.unistd.setresgid
-      libc.src.unistd.setreuid
       libc.src.unistd.setresuid
+      libc.src.unistd.setreuid
       libc.src.unistd.setuid
 
       # wchar.h entrypoints
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 6c37ece94a37b..e35ca9c7211ab 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -757,8 +757,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.unistd.setgid
       libc.src.unistd.setregid
       libc.src.unistd.setresgid
-      libc.src.unistd.setreuid
       libc.src.unistd.setresuid
+      libc.src.unistd.setreuid
       libc.src.unistd.setuid
     )
   endif()
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index b02bf6e4ca4a4..d023c473fd695 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1754,8 +1754,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.unistd.setgid
       libc.src.unistd.setregid
       libc.src.unistd.setresgid
-      libc.src.unistd.setreuid
       libc.src.unistd.setresuid
+      libc.src.unistd.setreuid
       libc.src.unistd.setuid
 
       # wchar.h entrypoints
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 336f26b0a9bca..d5a7a9d7c3732 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1790,8 +1790,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.unistd.setgid
       libc.src.unistd.setregid
       libc.src.unistd.setresgid
-      libc.src.unistd.setreuid
       libc.src.unistd.setresuid
+      libc.src.unistd.setreuid
       libc.src.unistd.setuid
 
       # wchar.h entrypoints



More information about the libc-commits mailing list