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. :^)
This commit is contained in:
Andreas Kling 2019-11-29 16:15:30 +01:00
parent ea52fe528a
commit e56daf547c
Notes: sideshowbarker 2024-07-19 11:02:00 +09:00
5 changed files with 27 additions and 5 deletions

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;
} }