From 8ef9b003adb7922d9154793b745b1127f418b483 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 19 Dec 2021 16:38:46 +0100 Subject: [PATCH] Kernel: Stop perf event stack walk on bogus userspace->kernel traversal When walking the stack to generate a perf_event sample, we now check if a userspace stack frame points back into kernel memory. It was possible to use this as an arbitrary kernel memory read. :^) --- Kernel/PerformanceEventBuffer.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp index 14ec6498cc..906c9c85e4 100644 --- a/Kernel/PerformanceEventBuffer.cpp +++ b/Kernel/PerformanceEventBuffer.cpp @@ -43,10 +43,21 @@ static Vector raw_backtrace(Fl FlatPtr stack_ptr = bp; // FIXME: Figure out how to remove this SmapDisabler without breaking profile stacks. SmapDisabler disabler; + // NOTE: The stack should always have kernel frames first, followed by userspace frames. + // If a userspace frame points back into kernel memory, something is afoot. + bool is_walking_userspace_stack = false; while (stack_ptr) { void* fault_at; if (!safe_memcpy(&stack_ptr_copy, (void*)stack_ptr, sizeof(FlatPtr), fault_at)) break; + if (!Memory::is_user_address(VirtualAddress { stack_ptr })) { + if (is_walking_userspace_stack) { + dbgln("SHENANIGANS! Userspace stack points back into kernel memory"); + break; + } + } else { + is_walking_userspace_stack = true; + } FlatPtr retaddr; if (!safe_memcpy(&retaddr, (void*)(stack_ptr + sizeof(FlatPtr)), sizeof(FlatPtr), fault_at)) break;