diff --git a/kernel/kernel/Debug.cpp b/kernel/kernel/Debug.cpp index 35100871..427229d3 100644 --- a/kernel/kernel/Debug.cpp +++ b/kernel/kernel/Debug.cpp @@ -7,6 +7,8 @@ #include #include +#include + #include #include @@ -14,6 +16,13 @@ bool g_disable_debug = false; +extern "C" bool safe_user_memcpy(void*, const void*, size_t); + +namespace Kernel +{ + extern bool g_safe_user_alloc_nonexisting; +} + namespace Debug { @@ -45,48 +54,25 @@ namespace Debug SpinLockGuard _(s_debug_lock); - const stackframe* frame = reinterpret_cast(bp); - - void* first_ip = frame->ip; - void* last_ip = 0; - bool first = true; + const bool temp = g_safe_user_alloc_nonexisting; + g_safe_user_alloc_nonexisting = false; + BAN::ScopeGuard alloc_restore([temp] { g_safe_user_alloc_nonexisting = temp; }); BAN::Formatter::print(Debug::putchar, "\e[36mStack trace:\r\n"); if (ip != 0) BAN::Formatter::print(Debug::putchar, " {}\r\n", reinterpret_cast(ip)); - while (frame) + stackframe frame; + if (!safe_user_memcpy(&frame, reinterpret_cast(bp), sizeof(stackframe))) + ; + else for (size_t depth = 0; depth < 64; depth++) { - if (!PageTable::is_valid_pointer((vaddr_t)frame)) - { - derrorln("invalid pointer {H}", (vaddr_t)frame); + BAN::Formatter::print(Debug::putchar, " {}\r\n", reinterpret_cast(frame.ip)); + if (!safe_user_memcpy(&frame, frame.bp, sizeof(stackframe))) break; - } - - if (PageTable::current().is_page_free((vaddr_t)frame & PAGE_ADDR_MASK)) - { - derrorln(" {} not mapped", frame); - break; - } - - BAN::Formatter::print(Debug::putchar, " {}\r\n", (void*)frame->ip); - - if (!first && frame->ip == first_ip) - { - derrorln("looping kernel panic :("); - break; - } - else if (!first && frame->ip == last_ip) - { - derrorln("repeating stack trace"); - break; - } - - last_ip = frame->ip; - frame = frame->bp; - first = false; } + BAN::Formatter::print(Debug::putchar, "\e[m"); } diff --git a/kernel/kernel/IDT.cpp b/kernel/kernel/IDT.cpp index 30006072..a78d2697 100644 --- a/kernel/kernel/IDT.cpp +++ b/kernel/kernel/IDT.cpp @@ -191,6 +191,8 @@ namespace Kernel }, }; + bool g_safe_user_alloc_nonexisting { true }; + extern "C" void cpp_isr_handler(uint32_t isr, uint32_t error, InterruptStack* interrupt_stack, const Registers* regs) { if (g_paniced) @@ -214,6 +216,16 @@ namespace Kernel PageFaultError page_fault_error; page_fault_error.raw = error; + const uint8_t* ip = reinterpret_cast(interrupt_stack->ip); + + if (!g_safe_user_alloc_nonexisting) for (const auto& safe_user : s_safe_user_page_faults) + { + if (ip < safe_user.ip_start || ip >= safe_user.ip_end) + continue; + interrupt_stack->ip = reinterpret_cast(safe_user.ip_fault); + return; + } + Processor::set_interrupt_state(InterruptState::Enabled); auto result = Process::current().allocate_page_for_demand_paging(regs->cr2, page_fault_error.write, page_fault_error.instruction); Processor::set_interrupt_state(InterruptState::Disabled); @@ -234,8 +246,7 @@ namespace Kernel if (result.value()) return; - const uint8_t* ip = reinterpret_cast(interrupt_stack->ip); - for (const auto& safe_user : s_safe_user_page_faults) + if (g_safe_user_alloc_nonexisting) for (const auto& safe_user : s_safe_user_page_faults) { if (ip < safe_user.ip_start || ip >= safe_user.ip_end) continue;