From a5d80f7e3b7443c2e76f33324736939d10bcf50f Mon Sep 17 00:00:00 2001 From: Jesse Date: Fri, 19 Jul 2019 21:08:26 +1000 Subject: [PATCH] Kernel: Only allow superuser to halt() the system (#342) Following the discussion in #334, shutdown must also have root-only run permissions. --- Kernel/Process.cpp | 15 +++++++++++++++ Kernel/Process.h | 1 + Kernel/Syscall.cpp | 9 ++------- Libraries/LibC/unistd.cpp | 6 ++++++ Libraries/LibC/unistd.h | 1 + Userland/shutdown.cpp | 9 ++++++--- 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index a8c3ae659e5..a119dad55b6 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2639,6 +2639,21 @@ int Process::sys$systrace(pid_t pid) return fd; } +int Process::sys$halt() +{ + if (!is_superuser()) + return -EPERM; + + dbgprintf("acquiring FS locks...\n"); + FS::lock_all(); + dbgprintf("syncing mounted filesystems...\n"); + FS::sync(); + dbgprintf("attempting system shutdown...\n"); + IO::out16(0x604, 0x2000); + + return ESUCCESS; +} + int Process::sys$reboot() { if (!is_superuser()) diff --git a/Kernel/Process.h b/Kernel/Process.h index 874ed84f9bd..d027cfe3a47 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -203,6 +203,7 @@ public: int sys$release_shared_buffer(int shared_buffer_id); int sys$seal_shared_buffer(int shared_buffer_id); int sys$get_shared_buffer_size(int shared_buffer_id); + int sys$halt(); int sys$reboot(); static void initialize(); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 4f17862e418..6f1b25132f4 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include #include #include @@ -285,12 +285,7 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3 case Syscall::SC_sched_getparam: return current->process().sys$sched_setparam((pid_t)arg1, (struct sched_param*)arg2); case Syscall::SC_halt: { - dbgprintf("<%u> halting! acquiring locks...\n"); - FS::lock_all(); - dbgprintf("<%u> halting! syncing...\n"); - FS::sync(); - dbgprintf("<%u> halting! bye, friends...\n"); - IO::out16(0x604, 0x2000); + return current->process().sys$halt(); break; } case Syscall::SC_reboot: { diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index a859bcd85be..4dd041224a8 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -515,6 +515,12 @@ int fsync(int fd) return 0; } +int halt() +{ + int rc = syscall(SC_halt); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + int reboot() { int rc = syscall(SC_reboot); diff --git a/Libraries/LibC/unistd.h b/Libraries/LibC/unistd.h index a84353dc5a6..cbf57265f3b 100644 --- a/Libraries/LibC/unistd.h +++ b/Libraries/LibC/unistd.h @@ -93,6 +93,7 @@ char* getlogin(); int chown(const char* pathname, uid_t, gid_t); int fchown(int fd, uid_t, gid_t); int ftruncate(int fd, off_t length); +int halt(); int reboot(); enum { diff --git a/Userland/shutdown.cpp b/Userland/shutdown.cpp index cd2ffe67c1d..0d1900fbf78 100644 --- a/Userland/shutdown.cpp +++ b/Userland/shutdown.cpp @@ -1,5 +1,6 @@ -#include #include +#include +#include int main(int argc, char** argv) { @@ -8,8 +9,10 @@ int main(int argc, char** argv) CArgsParserResult args = args_parser.parse(argc, argv); if (args.is_present("n")) { - syscall(SC_halt); - return 0; + if (halt() < 0) { + perror("shutdown"); + return 1; + } } else { args_parser.print_usage(); return 0;