Kaynağa Gözat

Kernel: Only allow superuser to halt() the system (#342)

Following the discussion in #334, shutdown must also have root-only
run permissions.
Jesse 6 yıl önce
ebeveyn
işleme
a5d80f7e3b

+ 15 - 0
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())

+ 1 - 0
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();

+ 2 - 7
Kernel/Syscall.cpp

@@ -1,7 +1,7 @@
 #include <Kernel/Arch/i386/CPU.h>
 #include <Kernel/Console.h>
-#include <Kernel/Process.h>
 #include <Kernel/IO.h>
+#include <Kernel/Process.h>
 #include <Kernel/ProcessTracer.h>
 #include <Kernel/Scheduler.h>
 #include <Kernel/Syscall.h>
@@ -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: {

+ 6 - 0
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);

+ 1 - 0
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 {

+ 6 - 3
Userland/shutdown.cpp

@@ -1,5 +1,6 @@
-#include <Kernel/Syscall.h>
 #include <LibCore/CArgsParser.h>
+#include <stdio.h>
+#include <unistd.h>
 
 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;