[libc-commits] [libc] f68ff0b - [libc] Implement seteuid and setegid in unistd (#233088)
via libc-commits
libc-commits at lists.llvm.org
Tue Oct 20 08:00:24 PDT 2026
Author: Aman Maurya
Date: 2026-10-20T20:30:18+05:30
New Revision: f68ff0be52cd2c42bbf89ed4bbb71ee1447e86c6
URL: https://github.com/llvm/llvm-project/commit/f68ff0be52cd2c42bbf89ed4bbb71ee1447e86c6
DIFF: https://github.com/llvm/llvm-project/commit/f68ff0be52cd2c42bbf89ed4bbb71ee1447e86c6.diff
LOG: [libc] Implement seteuid and setegid in unistd (#233088)
Implement the standard POSIX functions `seteuid` and `setegid` in
`<unistd.h>`.
Fixes #232380.
Assisted by Antigravity and reviewed by Aman Maurya.
Added:
libc/src/__support/OSUtil/linux/syscall_wrappers/setresgid.h
libc/src/__support/OSUtil/linux/syscall_wrappers/setresuid.h
libc/src/unistd/linux/setegid.cpp
libc/src/unistd/linux/seteuid.cpp
libc/src/unistd/setegid.h
libc/src/unistd/seteuid.h
libc/test/src/unistd/setegid_test.cpp
libc/test/src/unistd/seteuid_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/arm/entrypoints.txt
libc/config/linux/riscv/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/include/unistd.yaml
libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
libc/src/unistd/CMakeLists.txt
libc/src/unistd/linux/CMakeLists.txt
libc/test/src/unistd/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 6b68324f4e0ea6..995d286b420653 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1536,6 +1536,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
libc.src.time.tzset
# unistd.h entrypoints
+ libc.src.unistd.setegid
+ libc.src.unistd.seteuid
libc.src.unistd.setgid
libc.src.unistd.setregid
libc.src.unistd.setreuid
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index b1c04072b413b9..68df92046241a1 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -749,6 +749,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
libc.src.sys.ptrace.ptrace
# unistd.h entrypoints
+ libc.src.unistd.setegid
+ libc.src.unistd.seteuid
libc.src.unistd.setgid
libc.src.unistd.setregid
libc.src.unistd.setreuid
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 61fe9e7549e49a..6138d25f0981f3 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1738,6 +1738,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
libc.src.sys.ptrace.ptrace
# unistd.h entrypoints
+ libc.src.unistd.setegid
+ libc.src.unistd.seteuid
libc.src.unistd.setgid
libc.src.unistd.setregid
libc.src.unistd.setreuid
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 7f6e89485cc275..f736986da9cf93 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1774,6 +1774,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
libc.src.time.tzset
# unistd.h entrypoints
+ libc.src.unistd.setegid
+ libc.src.unistd.seteuid
libc.src.unistd.setgid
libc.src.unistd.setregid
libc.src.unistd.setreuid
diff --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml
index a94bf195a4eef3..ee59a2dc0fe2e4 100644
--- a/libc/include/unistd.yaml
+++ b/libc/include/unistd.yaml
@@ -550,6 +550,18 @@ functions:
- type: const void *__restrict
- type: void *
- type: ssize_t
+ - name: setegid
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: gid_t
+ - name: seteuid
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: uid_t
- name: setgid
standards:
- posix
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 4ee0268a836a0d..29facb2fbda2ec 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -959,6 +959,32 @@ add_header_library(
libc.src.__support.OSUtil.osutil
)
+add_header_library(
+ setresgid
+ HDRS
+ setresgid.h
+ DEPENDS
+ libc.hdr.types.gid_t
+ libc.include.sys_syscall
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.src.__support.OSUtil.osutil
+)
+
+add_header_library(
+ setresuid
+ HDRS
+ setresuid.h
+ DEPENDS
+ libc.hdr.types.uid_t
+ libc.include.sys_syscall
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.src.__support.OSUtil.osutil
+)
+
add_header_library(
setreuid
HDRS
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/setresgid.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/setresgid.h
new file mode 100644
index 00000000000000..df68ca97d78e56
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/setresgid.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Syscall wrapper for setresgid.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SETRESGID_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SETRESGID_H
+
+#include "hdr/types/gid_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> setresgid(gid_t rgid, gid_t egid, gid_t sgid) {
+#if defined(SYS_setresgid32)
+ return syscall_checked<int>(SYS_setresgid32, rgid, egid, sgid);
+#elif defined(SYS_setresgid)
+ return syscall_checked<int>(SYS_setresgid, rgid, egid, sgid);
+#else
+#error "SYS_setresgid and SYS_setresgid32 syscalls not available."
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SETRESGID_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/setresuid.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/setresuid.h
new file mode 100644
index 00000000000000..4574e9a28a6f67
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/setresuid.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Syscall wrapper for setresuid.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SETRESUID_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SETRESUID_H
+
+#include "hdr/types/uid_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> setresuid(uid_t ruid, uid_t euid, uid_t suid) {
+#if defined(SYS_setresuid32)
+ return syscall_checked<int>(SYS_setresuid32, ruid, euid, suid);
+#elif defined(SYS_setresuid)
+ return syscall_checked<int>(SYS_setresuid, ruid, euid, suid);
+#else
+#error "SYS_setresuid and SYS_setresuid32 syscalls not available."
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SETRESUID_H
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index aee321f599588f..4cbf4d9f26128b 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -406,6 +406,20 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.rmdir
)
+add_entrypoint_object(
+ setegid
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.setegid
+)
+
+add_entrypoint_object(
+ seteuid
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.seteuid
+)
+
add_entrypoint_object(
setgid
ALIAS
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index 4a24077f4f4c7f..0f80ea01cae7ba 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -740,6 +740,30 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ setegid
+ SRCS
+ setegid.cpp
+ HDRS
+ ../setegid.h
+ DEPENDS
+ libc.hdr.types.gid_t
+ libc.src.__support.OSUtil.linux.syscall_wrappers.setresgid
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ seteuid
+ SRCS
+ seteuid.cpp
+ HDRS
+ ../seteuid.h
+ DEPENDS
+ libc.hdr.types.uid_t
+ libc.src.__support.OSUtil.linux.syscall_wrappers.setresuid
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
setgid
SRCS
diff --git a/libc/src/unistd/linux/setegid.cpp b/libc/src/unistd/linux/setegid.cpp
new file mode 100644
index 00000000000000..0afb65638cbd41
--- /dev/null
+++ b/libc/src/unistd/linux/setegid.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 setegid.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/setegid.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, setegid, (gid_t gid)) {
+ // TODO: Implement setxid propagation across threads.
+ auto ret = linux_syscalls::setresgid(static_cast<gid_t>(-1), gid,
+ static_cast<gid_t>(-1));
+ if (!ret) {
+ libc_errno = ret.error();
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/linux/seteuid.cpp b/libc/src/unistd/linux/seteuid.cpp
new file mode 100644
index 00000000000000..50cc48d8e0c0f1
--- /dev/null
+++ b/libc/src/unistd/linux/seteuid.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 seteuid.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/seteuid.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, seteuid, (uid_t uid)) {
+ // TODO: Implement setxid propagation across threads.
+ auto ret = linux_syscalls::setresuid(static_cast<uid_t>(-1), uid,
+ static_cast<uid_t>(-1));
+ if (!ret) {
+ libc_errno = ret.error();
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/setegid.h b/libc/src/unistd/setegid.h
new file mode 100644
index 00000000000000..814e0d15b6c98d
--- /dev/null
+++ b/libc/src/unistd/setegid.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 setegid.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_SETEGID_H
+#define LLVM_LIBC_SRC_UNISTD_SETEGID_H
+
+#include "hdr/types/gid_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int setegid(gid_t gid);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_SETEGID_H
diff --git a/libc/src/unistd/seteuid.h b/libc/src/unistd/seteuid.h
new file mode 100644
index 00000000000000..efcae1f180f557
--- /dev/null
+++ b/libc/src/unistd/seteuid.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 seteuid.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_SETEUID_H
+#define LLVM_LIBC_SRC_UNISTD_SETEUID_H
+
+#include "hdr/types/uid_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int seteuid(uid_t uid);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_SETEUID_H
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 2e8d9bb8e2509f..08e42e3fe4c643 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -497,6 +497,36 @@ add_libc_test(
libc.test.UnitTest.ErrnoSetterMatcher
)
+add_libc_test(
+ setegid_test
+ SUITE
+ libc_unistd_unittests
+ SRCS
+ setegid_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.src.unistd.getegid
+ libc.src.unistd.getgid
+ libc.src.unistd.setegid
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
+
+add_libc_test(
+ seteuid_test
+ SUITE
+ libc_unistd_unittests
+ SRCS
+ seteuid_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.src.unistd.geteuid
+ libc.src.unistd.getuid
+ libc.src.unistd.seteuid
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
+
add_libc_test(
setgid_test
SUITE
diff --git a/libc/test/src/unistd/setegid_test.cpp b/libc/test/src/unistd/setegid_test.cpp
new file mode 100644
index 00000000000000..3f1cb78d5a8a37
--- /dev/null
+++ b/libc/test/src/unistd/setegid_test.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 setegid.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "src/unistd/getegid.h"
+#include "src/unistd/getgid.h"
+#include "src/unistd/setegid.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcSetEGidTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcSetEGidTest, SetCurrentEGid) {
+ // Setting the effective GID to the current effective GID should succeed.
+ ASSERT_THAT(LIBC_NAMESPACE::setegid(LIBC_NAMESPACE::getegid()), Succeeds());
+}
+
+TEST_F(LlvmLibcSetEGidTest, SetCurrentGid) {
+ // Setting the effective GID to the current real GID should succeed.
+ ASSERT_THAT(LIBC_NAMESPACE::setegid(LIBC_NAMESPACE::getgid()), Succeeds());
+}
+
+TEST_F(LlvmLibcSetEGidTest, UnprivilegedInvalidGid) {
+ if (LIBC_NAMESPACE::getgid() == 0)
+ return;
+ ASSERT_THAT(LIBC_NAMESPACE::setegid(static_cast<gid_t>(-2)),
+ Fails(any_of(EINVAL, EPERM)));
+}
diff --git a/libc/test/src/unistd/seteuid_test.cpp b/libc/test/src/unistd/seteuid_test.cpp
new file mode 100644
index 00000000000000..c9dcd7f729b96b
--- /dev/null
+++ b/libc/test/src/unistd/seteuid_test.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 seteuid.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "src/unistd/geteuid.h"
+#include "src/unistd/getuid.h"
+#include "src/unistd/seteuid.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcSetEUidTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcSetEUidTest, SetCurrentEUid) {
+ // Setting the effective UID to the current effective UID should succeed.
+ ASSERT_THAT(LIBC_NAMESPACE::seteuid(LIBC_NAMESPACE::geteuid()), Succeeds());
+}
+
+TEST_F(LlvmLibcSetEUidTest, SetCurrentUid) {
+ // Setting the effective UID to the current real UID should succeed.
+ ASSERT_THAT(LIBC_NAMESPACE::seteuid(LIBC_NAMESPACE::getuid()), Succeeds());
+}
+
+TEST_F(LlvmLibcSetEUidTest, UnprivilegedInvalidUid) {
+ if (LIBC_NAMESPACE::getuid() == 0)
+ return;
+ ASSERT_THAT(LIBC_NAMESPACE::seteuid(static_cast<uid_t>(-2)),
+ Fails(any_of(EINVAL, EPERM)));
+}
More information about the libc-commits
mailing list