From 3da1849c99e5c50171f7ccc3acd051aea98a7c31 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 8 Apr 2023 13:50:18 +0200 Subject: [PATCH] kernel+libc: Add set* and get* syscalls for UIDs and GIDs --- apps/CMakeLists.txt | 3 ++ apps/su.cpp | 32 ++++++++++++++ kernel/src/sys/id.cpp | 80 ++++++++++++++++++++++++++++++++++ libc/include/sys/types.h | 2 + libc/include/unistd.h | 24 ++++++++++ libc/src/unistd.cpp | 44 +++++++++++++++++++ libluna/include/luna/Syscall.h | 3 +- 7 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 apps/su.cpp diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 91d82fea..288cb943 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -9,6 +9,9 @@ endfunction() luna_app(init.cpp init) luna_app(env.cpp env) +luna_app(su.cpp su) +target_link_libraries(su PRIVATE os) + luna_app(sh.cpp sh) target_link_libraries(sh PRIVATE os) diff --git a/apps/su.cpp b/apps/su.cpp new file mode 100644 index 00000000..2141be81 --- /dev/null +++ b/apps/su.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + StringView id; + + if (geteuid() != 0) + { + fprintf(stderr, "su must be run as root!\n"); + return 1; + } + + os::ArgumentParser parser; + parser.add_positional_argument(id, "id"_sv, true); + parser.parse(argc, argv); + + int uid = atoi(id.chars()); + + if (uid == 0) + { + fprintf(stderr, "Already root!\n"); + return 1; + } + + setgid(uid); + setuid(uid); + + execl("/bin/sh", "sh", NULL); +} diff --git a/kernel/src/sys/id.cpp b/kernel/src/sys/id.cpp index fd5dfac7..21bbac08 100644 --- a/kernel/src/sys/id.cpp +++ b/kernel/src/sys/id.cpp @@ -10,3 +10,83 @@ Result sys_getppid(Registers*, SyscallArgs) { return Scheduler::current()->parent_id; } + +Result sys_getuid(Registers*, SyscallArgs) +{ + return Scheduler::current()->auth.uid; +} + +Result sys_geteuid(Registers*, SyscallArgs) +{ + return Scheduler::current()->auth.euid; +} + +Result sys_getgid(Registers*, SyscallArgs) +{ + return Scheduler::current()->auth.gid; +} + +Result sys_getegid(Registers*, SyscallArgs) +{ + return Scheduler::current()->auth.egid; +} + +Result sys_setuid(Registers*, SyscallArgs args) +{ + u32 uid = (u32)args[0]; + + Credentials& auth = Scheduler::current()->auth; + + if (auth.euid == 0) + { + auth.uid = auth.euid = auth.suid = uid; + return 0; + } + + if (uid != auth.uid && uid != auth.suid) return err(EPERM); + auth.euid = uid; + + return 0; +} + +Result sys_seteuid(Registers*, SyscallArgs args) +{ + u32 uid = (u32)args[0]; + + Credentials& auth = Scheduler::current()->auth; + + if (auth.euid != 0 && uid != auth.uid && uid != auth.suid) return err(EPERM); + auth.euid = uid; + + return 0; +} + +Result sys_setgid(Registers*, SyscallArgs args) +{ + u32 gid = (u32)args[0]; + + Credentials& auth = Scheduler::current()->auth; + + if (auth.euid == 0) + { + auth.gid = auth.egid = auth.sgid = gid; + return 0; + } + + if (gid != auth.gid && gid != auth.sgid) return err(EPERM); + auth.egid = gid; + + return 0; +} + +Result sys_setegid(Registers*, SyscallArgs args) +{ + u32 gid = (u32)args[0]; + + Credentials& auth = Scheduler::current()->auth; + + if (auth.euid != 0 && gid != auth.gid && gid != auth.sgid) return err(EPERM); + auth.egid = gid; + + return 0; +} diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h index aeecc9de..f769ab67 100644 --- a/libc/include/sys/types.h +++ b/libc/include/sys/types.h @@ -16,6 +16,8 @@ typedef __u64_t useconds_t; typedef __i64_t off_t; typedef __u64_t dev_t; typedef __u64_t ino_t; +typedef __u32_t uid_t; +typedef __u32_t gid_t; typedef off_t fpos_t; diff --git a/libc/include/unistd.h b/libc/include/unistd.h index ca851079..720f3a13 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -28,6 +28,30 @@ extern "C" /* Return the current process' parent process ID. */ pid_t getppid(void); + /* Return the current process' real user ID. */ + uid_t getuid(void); + + /* Return the current process' effective user ID. */ + uid_t geteuid(void); + + /* Return the current process' real group ID. */ + gid_t getgid(void); + + /* Return the current process' effective group ID. */ + gid_t getegid(void); + + /* Set the current process' user IDs. */ + int setuid(uid_t uid); + + /* Set the current process' effective user ID. */ + int seteuid(uid_t uid); + + /* Set the current process' group IDs. */ + int setgid(gid_t gid); + + /* Set the current process' effective group ID. */ + int setegid(gid_t gid); + /* Replace the current process with another one. On success, does not return. */ int execv(const char* path, char* const* argv); diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp index 415e95e8..9a9cfca2 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -31,6 +31,50 @@ extern "C" return (pid_t)syscall(SYS_getppid); } + uid_t getuid(void) + { + return (uid_t)syscall(SYS_getuid); + } + + uid_t geteuid(void) + { + return (uid_t)syscall(SYS_geteuid); + } + + gid_t getgid(void) + { + return (gid_t)syscall(SYS_getgid); + } + + gid_t getegid(void) + { + return (gid_t)syscall(SYS_getegid); + } + + int setuid(uid_t uid) + { + long rc = syscall(SYS_setuid, uid); + __errno_return(rc, int); + } + + int seteuid(uid_t uid) + { + long rc = syscall(SYS_seteuid, uid); + __errno_return(rc, int); + } + + int setgid(gid_t gid) + { + long rc = syscall(SYS_setgid, gid); + __errno_return(rc, int); + } + + int setegid(gid_t gid) + { + long rc = syscall(SYS_setegid, gid); + __errno_return(rc, int); + } + int execv(const char* path, char* const* argv) { return execve(path, argv, environ); diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index 113a00db..0b36611b 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -2,7 +2,8 @@ #define enumerate_syscalls(_e) \ _e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(open) _e(close) _e(read) _e(getpid) _e(write) \ - _e(lseek) _e(mkdir) _e(execve) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) + _e(lseek) _e(mkdir) _e(execve) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) \ + _e(geteuid) _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) enum Syscalls {