commit e0e52e4f2cdb946e49bd6b7ed44516e28d6f334e
parent 21a3e430c87ebfdb5e12aad01306e85a25fdfb4c
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 28 Aug 2022 00:26:24 +0200
unix: add getgroups, setgroups
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
6 files changed, 52 insertions(+), 7 deletions(-)
diff --git a/rt/+freebsd/syscalls.ha b/rt/+freebsd/syscalls.ha
@@ -323,6 +323,16 @@ export fn setresgid(gid: gid_t, egid: gid_t, sgid: gid_t) (void | errno) = {
wrap_return(syscall3(SYS_setresgid, gid: u64, egid: u64, sgid: u64))?;
};
+export fn getgroups(gids: []uint) (uint | errno) = {
+ return wrap_return(syscall2(SYS_getgroups,
+ len(gids): u64, gids: *[*]uint: uintptr: u64))?: uint;
+};
+
+export fn setgroups(gids: []uint) (void | errno) = {
+ wrap_return(syscall2(SYS_setgroups,
+ len(gids): u64, gids: *[*]uint: uintptr: u64))?;
+};
+
export fn getresuid(uid: *uid_t, euid: *uid_t, suid: *uid_t) (void | errno) = {
wrap_return(syscall3(SYS_getresuid,
uid: uintptr: u64,
diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha
@@ -692,6 +692,16 @@ export fn getresgid(gid: *gid_t, egid: *gid_t, sgid: *gid_t) (void | errno) = {
sgid: uintptr: u64))?;
};
+export fn getgroups(gids: []uint) (uint | errno) = {
+ return wrap_return(syscall2(SYS_getgroups,
+ len(gids): u64, gids: *[*]uint: uintptr: u64))?: uint;
+};
+
+export fn setgroups(gids: []uint) (void | errno) = {
+ wrap_return(syscall2(SYS_setgroups,
+ len(gids): u64, gids: *[*]uint: uintptr: u64))?;
+};
+
export fn getpriority(which: int, who: id_t) (int | errno) = {
return wrap_return(syscall2(SYS_setpriority,
which: u64, who: u64))?: int;
diff --git a/rt/+linux/types.ha b/rt/+linux/types.ha
@@ -24,6 +24,7 @@ export type timer_t = int;
export type clock_t = i64;
export type si_band_t = i64;
+export def NGROUPS_MAX: size = 32;
export def NSIG: int = 64;
export type sigset = struct {
@@ -214,7 +215,7 @@ export def MAP_HUGE_2GB: uint = 31 << 26;
export def MAP_HUGE_16GB: uint = 34 << 26;
export def PROT_NONE: uint = 0;
-export def PROT_READ: uint = 1;
+export def PROT_READ: uint = 1;
export def PROT_WRITE: uint = 2;
export def PROT_EXEC: uint = 4;
export def PROT_GROWSDOWN: uint = 0x01000000;
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -1337,7 +1337,8 @@ unix() {
+linux/pipe.ha \
+linux/umask.ha \
getuid.ha \
- setuid.ha
+ setuid.ha \
+ groups.ha
gen_ssa -plinux unix errors fs io
gen_srcs -pfreebsd unix \
@@ -1345,7 +1346,8 @@ unix() {
+freebsd/pipe.ha \
+freebsd/umask.ha \
getuid.ha \
- setuid.ha
+ setuid.ha \
+ groups.ha
gen_ssa -pfreebsd unix errors fs io
}
diff --git a/stdlib.mk b/stdlib.mk
@@ -2015,7 +2015,8 @@ stdlib_unix_linux_srcs = \
$(STDLIB)/unix/+linux/pipe.ha \
$(STDLIB)/unix/+linux/umask.ha \
$(STDLIB)/unix/getuid.ha \
- $(STDLIB)/unix/setuid.ha
+ $(STDLIB)/unix/setuid.ha \
+ $(STDLIB)/unix/groups.ha
$(HARECACHE)/unix/unix-linux.ssa: $(stdlib_unix_linux_srcs) $(stdlib_rt) $(stdlib_errors_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM))
@printf 'HAREC \t$@\n'
@@ -2029,7 +2030,8 @@ stdlib_unix_freebsd_srcs = \
$(STDLIB)/unix/+freebsd/pipe.ha \
$(STDLIB)/unix/+freebsd/umask.ha \
$(STDLIB)/unix/getuid.ha \
- $(STDLIB)/unix/setuid.ha
+ $(STDLIB)/unix/setuid.ha \
+ $(STDLIB)/unix/groups.ha
$(HARECACHE)/unix/unix-freebsd.ssa: $(stdlib_unix_freebsd_srcs) $(stdlib_rt) $(stdlib_errors_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM))
@printf 'HAREC \t$@\n'
@@ -4238,7 +4240,8 @@ testlib_unix_linux_srcs = \
$(STDLIB)/unix/+linux/pipe.ha \
$(STDLIB)/unix/+linux/umask.ha \
$(STDLIB)/unix/getuid.ha \
- $(STDLIB)/unix/setuid.ha
+ $(STDLIB)/unix/setuid.ha \
+ $(STDLIB)/unix/groups.ha
$(TESTCACHE)/unix/unix-linux.ssa: $(testlib_unix_linux_srcs) $(testlib_rt) $(testlib_errors_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM))
@printf 'HAREC \t$@\n'
@@ -4252,7 +4255,8 @@ testlib_unix_freebsd_srcs = \
$(STDLIB)/unix/+freebsd/pipe.ha \
$(STDLIB)/unix/+freebsd/umask.ha \
$(STDLIB)/unix/getuid.ha \
- $(STDLIB)/unix/setuid.ha
+ $(STDLIB)/unix/setuid.ha \
+ $(STDLIB)/unix/groups.ha
$(TESTCACHE)/unix/unix-freebsd.ssa: $(testlib_unix_freebsd_srcs) $(testlib_rt) $(testlib_errors_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM))
@printf 'HAREC \t$@\n'
diff --git a/unix/groups.ha b/unix/groups.ha
@@ -0,0 +1,18 @@
+use rt;
+
+// Returns a list of supplementary group IDs for the current process.
+export fn getgroups() []uint = {
+ static let gids: [rt::NGROUPS_MAX]uint = [0...];
+ const n = rt::getgroups(gids)!;
+ return gids[..n];
+};
+
+// Sets the list of supplementary group IDs which apply to the current process.
+// This generally requires elevated permissions.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setgroups is a grave security issue in your program,
+// and therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setgroups(gids: []uint) void = rt::setgroups(gids)!;