diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index 2d4520a6..dbc6c394 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -101,6 +101,7 @@ namespace Kernel BAN::ErrorOr write(off_t, BAN::ConstByteSpan buffer); BAN::ErrorOr truncate(size_t); BAN::ErrorOr chmod(mode_t); + BAN::ErrorOr chown(uid_t, gid_t); bool has_data() const; protected: @@ -119,6 +120,7 @@ namespace Kernel virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); } + virtual BAN::ErrorOr chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); } virtual bool has_data_impl() const { dwarnln("nonblock not supported"); return true; } protected: diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 7f1e882f..35922a27 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -108,6 +108,7 @@ namespace Kernel BAN::ErrorOr sys_pread(int fd, void* buffer, size_t count, off_t offset); BAN::ErrorOr sys_chmod(const char*, mode_t); + BAN::ErrorOr sys_chown(const char*, uid_t, gid_t); BAN::ErrorOr sys_pipe(int fildes[2]); BAN::ErrorOr sys_dup(int fildes); diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index 2f3c5a37..c5722dfc 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -41,6 +41,9 @@ namespace Kernel virtual void clear() = 0; + virtual BAN::ErrorOr chmod_impl(mode_t) override; + virtual BAN::ErrorOr chown_impl(uid_t, gid_t) override; + virtual bool has_data_impl() const override; protected: diff --git a/kernel/kernel/FS/Inode.cpp b/kernel/kernel/FS/Inode.cpp index 7f0311a8..d162316c 100644 --- a/kernel/kernel/FS/Inode.cpp +++ b/kernel/kernel/FS/Inode.cpp @@ -141,6 +141,12 @@ namespace Kernel return chmod_impl(mode); } + BAN::ErrorOr Inode::chown(uid_t uid, gid_t gid) + { + LockGuard _(m_lock); + return chown_impl(uid, gid); + } + bool Inode::has_data() const { LockGuard _(m_lock); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index b984d345..c2b9abc4 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -886,6 +886,18 @@ namespace Kernel return 0; } + BAN::ErrorOr Process::sys_chown(const char* path, uid_t uid, gid_t gid) + { + LockGuard _(m_lock); + validate_string_access(path); + + auto absolute_path = TRY(absolute_path_of(path)); + auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_WRONLY)); + TRY(file.inode->chown(uid, gid)); + + return 0; + } + BAN::ErrorOr Process::sys_pipe(int fildes[2]) { LockGuard _(m_lock); diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 128c8d86..4e8b54bc 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -211,6 +211,9 @@ namespace Kernel case SYS_PREAD: ret = Process::current().sys_pread((int)arg1, (void*)arg2, (size_t)arg3, (off_t)arg4); break; + case SYS_CHOWN: + ret = Process::current().sys_chown((const char*)arg1, (uid_t)arg2, (gid_t)arg3); + break; default: dwarnln("Unknown syscall {}", syscall); break; diff --git a/kernel/kernel/Terminal/Serial.cpp b/kernel/kernel/Terminal/Serial.cpp index 877c90c6..f756fcbd 100644 --- a/kernel/kernel/Terminal/Serial.cpp +++ b/kernel/kernel/Terminal/Serial.cpp @@ -179,7 +179,7 @@ namespace Kernel } SerialTTY::SerialTTY(Serial serial) - : TTY(0660, 0, 0) + : TTY(0600, 0, 0) , m_serial(serial) , m_rdev(next_rdev()) { diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index bf8ffc4e..297c756c 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -105,6 +105,21 @@ namespace Kernel initialized = true; } + BAN::ErrorOr TTY::chmod_impl(mode_t mode) + { + ASSERT((mode & Inode::Mode::TYPE_MASK) == 0); + m_inode_info.mode &= Inode::Mode::TYPE_MASK; + m_inode_info.mode |= mode; + return {}; + } + + BAN::ErrorOr TTY::chown_impl(uid_t uid, gid_t gid) + { + m_inode_info.uid = uid; + m_inode_info.gid = gid; + return {}; + } + void TTY::on_key_event(Input::KeyEvent event) { LockGuard _(m_lock); diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index dc190f99..9bed8de3 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -42,7 +42,7 @@ namespace Kernel } VirtualTTY::VirtualTTY(TerminalDriver* driver) - : TTY(0666, 0, 0) + : TTY(0600, 0, 0) , m_terminal_driver(driver) , m_rdev(next_rdev()) { diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 9cd90cd8..bfa5cbac 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -61,6 +61,7 @@ __BEGIN_DECLS #define SYS_READLINKAT 60 #define SYS_MSYNC 61 #define SYS_PREAD 62 +#define SYS_CHOWN 63 __END_DECLS diff --git a/libc/unistd.cpp b/libc/unistd.cpp index 75977fb4..af4e85d4 100644 --- a/libc/unistd.cpp +++ b/libc/unistd.cpp @@ -270,6 +270,11 @@ int chdir(const char* path) return syscall(SYS_SET_PWD, path); } +int chown(const char* path, uid_t owner, gid_t group) +{ + return syscall(SYS_CHOWN, path, owner, group); +} + void sync(void) { syscall(SYS_SYNC, false); diff --git a/userspace/init/main.cpp b/userspace/init/main.cpp index c1acf03f..53520dde 100644 --- a/userspace/init/main.cpp +++ b/userspace/init/main.cpp @@ -63,6 +63,18 @@ int main() if (pwd == nullptr) continue; + if (chown("/dev/tty", pwd->pw_uid, pwd->pw_gid) == -1) + { + perror("chown"); + continue; + } + + if (chmod("/dev/tty", 0600) == -1) + { + perror("chmod"); + continue; + } + pid_t pid = fork(); if (pid == 0) {