kernel+libc: Add support for supplementary groups (2/2)

Adds system calls for setting and getting groups, along with libc wrappers.
This commit is contained in:
apio 2023-11-22 20:35:43 +01:00
parent 3ad23eab21
commit 8a90db837b
Signed by: apio
GPG Key ID: B8A7D06E42258954
7 changed files with 79 additions and 1 deletions

View File

@ -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
{

View File

@ -237,3 +237,54 @@ Result<u64> sys_fchownat(Registers*, SyscallArgs args)
return 0;
}
Result<u64> 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<usize>(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<u64> 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;
}

View File

@ -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

View File

@ -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

View File

@ -5,6 +5,8 @@
#include <luna/Vector.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
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);
}
}

View File

@ -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);
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <luna/Alloc.h>
#include <luna/CString.h>
#include <luna/Common.h>
#include <luna/Result.h>
#include <luna/Slice.h>
#include <luna/Types.h>
@ -245,6 +246,12 @@ template <typename T> class Vector
return other;
}
template <typename Callback> 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 };