diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-11-29 16:15:30 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-11-29 16:30:05 +0100 |
commit | e56daf547c120adfcdab1e1e8ea189a1f369bd0c (patch) | |
tree | 89d1aac5b5ccdc6c0aa25b735a351b5623b6f139 /Kernel | |
parent | ea52fe528a1b34590661c4556b6a4bbf68bb75f0 (diff) | |
download | serenity-e56daf547c120adfcdab1e1e8ea189a1f369bd0c.zip |
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. :^)
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Syscall.cpp | 13 | ||||
-rw-r--r-- | Kernel/VM/MemoryManager.cpp | 1 | ||||
-rw-r--r-- | Kernel/VM/MemoryManager.h | 8 |
3 files changed, 17 insertions, 5 deletions
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 708bfc23b3..1bd5e7e71c 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -105,6 +105,19 @@ void syscall_trap_entry(RegisterDump regs) 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(); u32 function = regs.eax; u32 arg1 = regs.edx; diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index 540081d26c..5e5c5a9b88 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/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) { - ASSERT_INTERRUPTS_DISABLED(); if (auto* region = kernel_region_from_vaddr(vaddr)) return region; return user_region_from_vaddr(process, vaddr); diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h index 619f95630c..b4c7cac06d 100644 --- a/Kernel/VM/MemoryManager.h +++ b/Kernel/VM/MemoryManager.h @@ -1,6 +1,5 @@ #pragma once -#include <AK/String.h> #include <AK/Badge.h> #include <AK/Bitmap.h> #include <AK/ByteBuffer.h> @@ -8,6 +7,7 @@ #include <AK/NonnullRefPtrVector.h> #include <AK/RefCounted.h> #include <AK/RefPtr.h> +#include <AK/String.h> #include <AK/Types.h> #include <AK/Vector.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: MemoryManager(u32 physical_address_for_kernel_page_tables); ~MemoryManager(); @@ -96,9 +99,6 @@ private: 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* kernel_region_from_vaddr(VirtualAddress); |