From 8a90db837bfb06e02017256d77a15d4357595638 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 22 Nov 2023 20:35:43 +0100 Subject: [PATCH] kernel+libc: Add support for supplementary groups (2/2) Adds system calls for setting and getting groups, along with libc wrappers. --- kernel/src/api/Syscall.h | 2 +- kernel/src/sys/id.cpp | 51 +++++++++++++++++++++++++++++++++++ libc/include/grp.h | 3 +++ libc/include/unistd.h | 3 +++ libc/src/grp.cpp | 8 ++++++ libc/src/unistd.cpp | 6 +++++ libluna/include/luna/Vector.h | 7 +++++ 7 files changed, 79 insertions(+), 1 deletion(-) diff --git a/kernel/src/api/Syscall.h b/kernel/src/api/Syscall.h index f05dd6fe..f6fd7960 100644 --- a/kernel/src/api/Syscall.h +++ b/kernel/src/api/Syscall.h @@ -9,7 +9,7 @@ _e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \ _e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) \ _e(truncate) _e(ftruncate) _e(utimensat) _e(setitimer) _e(pledge) _e(memstat) \ - _e(setsid) _e(getsid) + _e(setsid) _e(getsid) _e(getgroups) _e(setgroups) enum Syscalls { diff --git a/kernel/src/sys/id.cpp b/kernel/src/sys/id.cpp index 7b7bb7c1..12dadd98 100644 --- a/kernel/src/sys/id.cpp +++ b/kernel/src/sys/id.cpp @@ -237,3 +237,54 @@ Result sys_fchownat(Registers*, SyscallArgs args) return 0; } + +Result sys_getgroups(Registers*, SyscallArgs args) +{ + int ngroups = (int)args[0]; + gid_t* grouplist = (gid_t*)args[1]; + + auto* current = Scheduler::current(); + + TRY(check_pledge(current, Promise::p_stdio)); + + if (!ngroups) return current->extra_groups.size(); + if (ngroups < 0) return err(EINVAL); + + if (static_cast(ngroups) < current->extra_groups.size()) return err(EINVAL); + + if (!MemoryManager::copy_to_user(grouplist, current->extra_groups.data(), + current->extra_groups.size() * sizeof(gid_t))) + return err(EFAULT); + + return current->extra_groups.size(); +} + +Result sys_setgroups(Registers*, SyscallArgs args) +{ + int ngroups = (int)args[0]; + const gid_t* grouplist = (const gid_t*)args[1]; + + auto* current = Scheduler::current(); + + TRY(check_pledge(current, Promise::p_id)); + + Credentials& auth = current->auth; + if (auth.euid != 0) return err(EPERM); + + if (!ngroups) + { + current->extra_groups.clear(); + return 0; + } + + if (ngroups < 0 || ngroups > 32) return err(EINVAL); + + TRY(current->extra_groups.try_reserve(ngroups)); + + current->extra_groups.mutate([&](gid_t* list, usize) -> usize { + if (MemoryManager::copy_from_user(grouplist, list, ngroups * sizeof(gid_t))) return ngroups; + return current->extra_groups.size(); + }); + + return 0; +} diff --git a/libc/include/grp.h b/libc/include/grp.h index e00eca0e..e7bf6294 100644 --- a/libc/include/grp.h +++ b/libc/include/grp.h @@ -33,6 +33,9 @@ extern "C" /* End group file parsing. */ void endgrent(void); + /* Set this process's list of supplementary groups. */ + int setgroups(int size, const gid_t* list); + #ifdef __cplusplus } #endif diff --git a/libc/include/unistd.h b/libc/include/unistd.h index ef7cdca4..74c5ff64 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -205,6 +205,9 @@ extern "C" /* Restrict system operations. */ int pledge(const char* promises, const char* execpromises); + /* Get this process's list of supplementary groups. */ + int getgroups(int size, gid_t* list); + #ifdef __cplusplus } #endif diff --git a/libc/src/grp.cpp b/libc/src/grp.cpp index d6a46905..3b4aaf6b 100644 --- a/libc/src/grp.cpp +++ b/libc/src/grp.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include static struct group grp; static FILE* f { nullptr }; @@ -112,4 +114,10 @@ extern "C" f = nullptr; } } + + int setgroups(int size, const gid_t* list) + { + long rc = syscall(SYS_setgroups, size, list); + __errno_return(rc, int); + } } diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp index bb54e0ee..69ae625c 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -545,4 +545,10 @@ extern "C" long rc = syscall(SYS_setsid); __errno_return(rc, pid_t); } + + int getgroups(int size, gid_t* list) + { + long rc = syscall(SYS_getgroups, size, list); + __errno_return(rc, int); + } } diff --git a/libluna/include/luna/Vector.h b/libluna/include/luna/Vector.h index 28a578c5..6c7eb068 100644 --- a/libluna/include/luna/Vector.h +++ b/libluna/include/luna/Vector.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -245,6 +246,12 @@ template class Vector return other; } + template void mutate(Callback callback) + { + usize size = callback(m_data, m_capacity); + m_size = min(m_capacity, size); + } + private: T* m_data { nullptr }; usize m_capacity { 0 };