mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:57:36 +00:00
Kernel: Fix TOCTOU in syscall entry region validation
We were doing stack and syscall-origin region validations before taking the big process lock. There was a window of time where those regions could then be unmapped/remapped by another thread before we proceed with our syscall. This patch closes that window, and makes sys$get_stack_bounds() rely on the fact that we now know the userspace stack pointer to be valid. Thanks to @BenWiederhake for spotting this! :^)
This commit is contained in:
parent
10b7f6b77e
commit
4188373020
2 changed files with 6 additions and 4 deletions
|
@ -169,6 +169,9 @@ void syscall_handler(TrapFrame* trap)
|
||||||
PANIC("Syscall from process with IOPL != 0");
|
PANIC("Syscall from process with IOPL != 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: We take the big process lock before inspecting memory regions.
|
||||||
|
process.big_lock().lock();
|
||||||
|
|
||||||
if (!MM.validate_user_stack(process, VirtualAddress(regs.userspace_esp))) {
|
if (!MM.validate_user_stack(process, VirtualAddress(regs.userspace_esp))) {
|
||||||
dbgln("Invalid stack pointer: {:p}", regs.userspace_esp);
|
dbgln("Invalid stack pointer: {:p}", regs.userspace_esp);
|
||||||
handle_crash(regs, "Bad stack on syscall entry", SIGSTKFLT);
|
handle_crash(regs, "Bad stack on syscall entry", SIGSTKFLT);
|
||||||
|
@ -190,7 +193,6 @@ void syscall_handler(TrapFrame* trap)
|
||||||
handle_crash(regs, "Syscall from non-syscall region", SIGSEGV);
|
handle_crash(regs, "Syscall from non-syscall region", SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
process.big_lock().lock();
|
|
||||||
u32 function = regs.eax;
|
u32 function = regs.eax;
|
||||||
u32 arg1 = regs.edx;
|
u32 arg1 = regs.edx;
|
||||||
u32 arg2 = regs.ecx;
|
u32 arg2 = regs.ecx;
|
||||||
|
|
|
@ -34,9 +34,9 @@ int Process::sys$get_stack_bounds(FlatPtr* user_stack_base, size_t* user_stack_s
|
||||||
{
|
{
|
||||||
FlatPtr stack_pointer = Thread::current()->get_register_dump_from_stack().userspace_esp;
|
FlatPtr stack_pointer = Thread::current()->get_register_dump_from_stack().userspace_esp;
|
||||||
auto* stack_region = space().find_region_containing(Range { VirtualAddress(stack_pointer), 1 });
|
auto* stack_region = space().find_region_containing(Range { VirtualAddress(stack_pointer), 1 });
|
||||||
if (!stack_region) {
|
|
||||||
PANIC("sys$get_stack_bounds: No stack region found for process");
|
// The syscall handler should have killed us if we had an invalid stack pointer.
|
||||||
}
|
ASSERT(stack_region);
|
||||||
|
|
||||||
FlatPtr stack_base = stack_region->range().base().get();
|
FlatPtr stack_base = stack_region->range().base().get();
|
||||||
size_t stack_size = stack_region->size();
|
size_t stack_size = stack_region->size();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue