From a12e19c0152e1236a0e26a0b82a2a8c10ba8a55b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 28 Jan 2022 15:04:34 +0100 Subject: [PATCH] Kernel: Move kernel region checks from x86 page fault handler to MM Ideally the x86 fault handler would only do x86 specific things and delegate the rest of the work to MemoryManager. This patch moves some of the address checks to a more generic place. --- Kernel/Arch/x86/common/Interrupts.cpp | 16 ---------------- Kernel/Memory/MemoryManager.cpp | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Kernel/Arch/x86/common/Interrupts.cpp b/Kernel/Arch/x86/common/Interrupts.cpp index 0575154b60..417b5dae35 100644 --- a/Kernel/Arch/x86/common/Interrupts.cpp +++ b/Kernel/Arch/x86/common/Interrupts.cpp @@ -327,22 +327,6 @@ void page_fault_handler(TrapFrame* trap) return handle_crash(regs, "Bad stack on page fault", SIGSEGV); } - if (fault_address >= (FlatPtr)&start_of_ro_after_init && fault_address < (FlatPtr)&end_of_ro_after_init) { - dump(regs); - PANIC("Attempt to write into READONLY_AFTER_INIT section"); - } - - if (fault_address >= (FlatPtr)&start_of_unmap_after_init && fault_address < (FlatPtr)&end_of_unmap_after_init) { - dump(regs); - auto sym = symbolicate_kernel_address(fault_address); - PANIC("Attempt to access UNMAP_AFTER_INIT section ({:p}: {})", fault_address, sym ? sym->name : "(Unknown)"); - } - - if (fault_address >= (FlatPtr)&start_of_kernel_ksyms && fault_address < (FlatPtr)&end_of_kernel_ksyms) { - dump(regs); - PANIC("Attempt to access KSYMS section"); - } - PageFault fault { regs.exception_code, VirtualAddress { fault_address } }; auto response = MM.handle_page_fault(fault); diff --git a/Kernel/Memory/MemoryManager.cpp b/Kernel/Memory/MemoryManager.cpp index d76a802ed0..d6b0701b6d 100644 --- a/Kernel/Memory/MemoryManager.cpp +++ b/Kernel/Memory/MemoryManager.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -720,6 +721,22 @@ Region* MemoryManager::find_region_from_vaddr(VirtualAddress vaddr) PageFaultResponse MemoryManager::handle_page_fault(PageFault const& fault) { VERIFY_INTERRUPTS_DISABLED(); + + auto faulted_in_range = [&fault](auto const* start, auto const* end) { + return fault.vaddr() >= VirtualAddress { start } && fault.vaddr() < VirtualAddress { end }; + }; + + if (faulted_in_range(&start_of_ro_after_init, &end_of_ro_after_init)) + PANIC("Attempt to write into READONLY_AFTER_INIT section"); + + if (faulted_in_range(&start_of_unmap_after_init, &end_of_unmap_after_init)) { + auto const* kernel_symbol = symbolicate_kernel_address(fault.vaddr().get()); + PANIC("Attempt to access UNMAP_AFTER_INIT section ({:p}: {})", fault.vaddr(), kernel_symbol ? kernel_symbol->name : "(Unknown)"); + } + + if (faulted_in_range(&start_of_kernel_ksyms, &end_of_kernel_ksyms)) + PANIC("Attempt to access KSYMS section"); + if (Processor::current_in_irq()) { dbgln("CPU[{}] BUG! Page fault while handling IRQ! code={}, vaddr={}, irq level: {}", Processor::current_id(), fault.code(), fault.vaddr(), Processor::current_in_irq());