소스 검색

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. :^)
Andreas Kling 3 년 전
부모
커밋
8ef9b003ad
1개의 변경된 파일11개의 추가작업 그리고 0개의 파일을 삭제
  1. 11 0
      Kernel/PerformanceEventBuffer.cpp

+ 11 - 0
Kernel/PerformanceEventBuffer.cpp

@@ -43,10 +43,21 @@ static Vector<FlatPtr, PerformanceEvent::max_stack_frame_count> 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;