hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mrt/+freebsd/syscalls.ha | 10++++++++++
Mrt/+linux/syscalls.ha | 10++++++++++
Mrt/+linux/types.ha | 3++-
Mscripts/gen-stdlib | 6++++--
Mstdlib.mk | 12++++++++----
Aunix/groups.ha | 18++++++++++++++++++
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)!;