Przeglądaj źródła

Kernel: Disallow syscalls from writeable memory

Processes will now crash with SIGSEGV if they attempt making a syscall
from PROT_WRITE memory.

This neat idea comes from OpenBSD. :^)
Andreas Kling 5 lat temu
rodzic
commit
e56daf547c

+ 1 - 0
Base/usr/share/man/man1/crash.md

@@ -27,6 +27,7 @@ kinds of crashes.
 * `-r`: Write to read-only memory.
 * `-r`: Write to read-only memory.
 * `-T`: Make a syscall while using an invalid stack pointer.
 * `-T`: Make a syscall while using an invalid stack pointer.
 * `-t`: Trigger a page fault while using an invalid stack pointer.
 * `-t`: Trigger a page fault while using an invalid stack pointer.
+* `-S`: Make a syscall from writeable memory.
 
 
 ## Examples
 ## Examples
 
 

+ 13 - 0
Kernel/Syscall.cpp

@@ -105,6 +105,19 @@ void syscall_trap_entry(RegisterDump regs)
         ASSERT_NOT_REACHED();
         ASSERT_NOT_REACHED();
     }
     }
 
 
+    auto* calling_region = MM.region_from_vaddr(process, VirtualAddress(regs.eip));
+    if (!calling_region) {
+        dbgprintf("Syscall from %p which has no region\n", regs.eip);
+        handle_crash(regs, "Syscall from unknown region", SIGSEGV);
+        ASSERT_NOT_REACHED();
+    }
+
+    if (calling_region->is_writable()) {
+        dbgprintf("Syscall from writable memory at %p\n", regs.eip);
+        handle_crash(regs, "Syscall from writable memory", SIGSEGV);
+        ASSERT_NOT_REACHED();
+    }
+
     process.big_lock().lock();
     process.big_lock().lock();
     u32 function = regs.eax;
     u32 function = regs.eax;
     u32 arg1 = regs.edx;
     u32 arg1 = regs.edx;

+ 0 - 1
Kernel/VM/MemoryManager.cpp

@@ -289,7 +289,6 @@ Region* MemoryManager::user_region_from_vaddr(Process& process, VirtualAddress v
 
 
 Region* MemoryManager::region_from_vaddr(Process& process, VirtualAddress vaddr)
 Region* MemoryManager::region_from_vaddr(Process& process, VirtualAddress vaddr)
 {
 {
-    ASSERT_INTERRUPTS_DISABLED();
     if (auto* region = kernel_region_from_vaddr(vaddr))
     if (auto* region = kernel_region_from_vaddr(vaddr))
         return region;
         return region;
     return user_region_from_vaddr(process, vaddr);
     return user_region_from_vaddr(process, vaddr);

+ 4 - 4
Kernel/VM/MemoryManager.h

@@ -1,6 +1,5 @@
 #pragma once
 #pragma once
 
 
-#include <AK/String.h>
 #include <AK/Badge.h>
 #include <AK/Badge.h>
 #include <AK/Bitmap.h>
 #include <AK/Bitmap.h>
 #include <AK/ByteBuffer.h>
 #include <AK/ByteBuffer.h>
@@ -8,6 +7,7 @@
 #include <AK/NonnullRefPtrVector.h>
 #include <AK/NonnullRefPtrVector.h>
 #include <AK/RefCounted.h>
 #include <AK/RefCounted.h>
 #include <AK/RefPtr.h>
 #include <AK/RefPtr.h>
+#include <AK/String.h>
 #include <AK/Types.h>
 #include <AK/Types.h>
 #include <AK/Vector.h>
 #include <AK/Vector.h>
 #include <AK/Weakable.h>
 #include <AK/Weakable.h>
@@ -79,6 +79,9 @@ public:
         }
         }
     }
     }
 
 
+    static Region* region_from_vaddr(Process&, VirtualAddress);
+    static const Region* region_from_vaddr(const Process&, VirtualAddress);
+
 private:
 private:
     MemoryManager(u32 physical_address_for_kernel_page_tables);
     MemoryManager(u32 physical_address_for_kernel_page_tables);
     ~MemoryManager();
     ~MemoryManager();
@@ -96,9 +99,6 @@ private:
 
 
     void create_identity_mapping(PageDirectory&, VirtualAddress, size_t length);
     void create_identity_mapping(PageDirectory&, VirtualAddress, size_t length);
 
 
-    static Region* region_from_vaddr(Process&, VirtualAddress);
-    static const Region* region_from_vaddr(const Process&, VirtualAddress);
-
     static Region* user_region_from_vaddr(Process&, VirtualAddress);
     static Region* user_region_from_vaddr(Process&, VirtualAddress);
     static Region* kernel_region_from_vaddr(VirtualAddress);
     static Region* kernel_region_from_vaddr(VirtualAddress);
 
 

+ 9 - 0
Userland/crash.cpp

@@ -1,4 +1,5 @@
 #include <AK/String.h>
 #include <AK/String.h>
+#include <Kernel/Syscall.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/mman.h>
@@ -24,6 +25,7 @@ int main(int argc, char** argv)
         WriteToReadonlyMemory,
         WriteToReadonlyMemory,
         InvalidStackPointerOnSyscall,
         InvalidStackPointerOnSyscall,
         InvalidStackPointerOnPageFault,
         InvalidStackPointerOnPageFault,
+        SyscallFromWritableMemory,
     };
     };
     Mode mode = SegmentationViolation;
     Mode mode = SegmentationViolation;
 
 
@@ -52,6 +54,8 @@ int main(int argc, char** argv)
         mode = InvalidStackPointerOnSyscall;
         mode = InvalidStackPointerOnSyscall;
     else if (String(argv[1]) == "-t")
     else if (String(argv[1]) == "-t")
         mode = InvalidStackPointerOnPageFault;
         mode = InvalidStackPointerOnPageFault;
+    else if (String(argv[1]) == "-S")
+        mode = SyscallFromWritableMemory;
     else
     else
         print_usage_and_exit();
         print_usage_and_exit();
 
 
@@ -152,6 +156,11 @@ int main(int argc, char** argv)
         ASSERT_NOT_REACHED();
         ASSERT_NOT_REACHED();
     }
     }
 
 
+    if (mode == SyscallFromWritableMemory) {
+        u8 buffer[] = { 0xb8, Syscall::SC_getuid, 0, 0, 0, 0xcd, 0x82 };
+        ((void(*)())buffer)();
+    }
+
     ASSERT_NOT_REACHED();
     ASSERT_NOT_REACHED();
     return 0;
     return 0;
 }
 }