diff --git a/kernel/src/sys/id.cpp b/kernel/src/sys/id.cpp index 21bbac08..ab4b2b82 100644 --- a/kernel/src/sys/id.cpp +++ b/kernel/src/sys/id.cpp @@ -1,3 +1,4 @@ +#include "memory/MemoryManager.h" #include "sys/Syscall.h" #include "thread/Scheduler.h" @@ -90,3 +91,36 @@ Result sys_setegid(Registers*, SyscallArgs args) return 0; } + +Result sys_chmod(Registers*, SyscallArgs args) +{ + auto path = TRY(MemoryManager::strdup_from_user(args[0])); + mode_t mode = (mode_t)args[1]; + + Credentials& auth = Scheduler::current()->auth; + + auto inode = TRY(VFS::resolve_path(path.chars(), auth)); + + if (auth.euid != 0 && auth.euid != inode->uid()) return err(EPERM); + + TRY(inode->chmod(mode)); + + return 0; +} + +Result sys_chown(Registers*, SyscallArgs args) +{ + auto path = TRY(MemoryManager::strdup_from_user(args[0])); + u32 uid = (u32)args[1]; + u32 gid = (u32)args[2]; + + Credentials& auth = Scheduler::current()->auth; + + auto inode = TRY(VFS::resolve_path(path.chars(), auth)); + + if (auth.euid != 0) return err(EPERM); + + TRY(inode->chown(uid == (u32)-1 ? inode->uid() : uid, gid == (u32)-1 ? inode->gid() : gid)); + + return 0; +} diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 720f3a13..a8c1bcfc 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -52,6 +52,12 @@ extern "C" /* Set the current process' effective group ID. */ int setegid(gid_t gid); + /* Change the mode bits of a file. */ + int chmod(const char* path, mode_t mode); + + /* Change the owner and group of a file. */ + int chown(const char* path, uid_t uid, 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 9a9cfca2..845f0235 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -75,6 +75,18 @@ extern "C" __errno_return(rc, int); } + int chmod(const char* path, mode_t mode) + { + long rc = syscall(SYS_chmod, path, mode); + __errno_return(rc, int); + } + + int chown(const char* path, uid_t uid, gid_t gid) + { + long rc = syscall(SYS_chown, path, uid, 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 0b36611b..db35e950 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -3,7 +3,7 @@ #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(getuid) \ - _e(geteuid) _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) + _e(geteuid) _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(chmod) _e(chown) enum Syscalls {