diff options
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Arch/x86/CPU.h | 2 | ||||
-rw-r--r-- | Kernel/Arch/x86/common/Interrupts.cpp | 16 | ||||
-rw-r--r-- | Kernel/Memory/MemoryManager.cpp | 8 | ||||
-rw-r--r-- | Kernel/Thread.cpp | 6 | ||||
-rw-r--r-- | Kernel/Thread.h | 1 |
5 files changed, 23 insertions, 10 deletions
diff --git a/Kernel/Arch/x86/CPU.h b/Kernel/Arch/x86/CPU.h index d0c7f54259..99d579c287 100644 --- a/Kernel/Arch/x86/CPU.h +++ b/Kernel/Arch/x86/CPU.h @@ -36,7 +36,7 @@ inline u32 get_iopl_from_eflags(u32 eflags) const DescriptorTablePointer& get_gdtr(); const DescriptorTablePointer& get_idtr(); -[[noreturn]] void handle_crash(RegisterState const&, char const* description, int signal, bool out_of_memory = false); +void handle_crash(RegisterState const&, char const* description, int signal, bool out_of_memory = false); #define LSW(x) ((u32)(x)&0xFFFF) #define MSW(x) (((u32)(x) >> 16) & 0xFFFF) diff --git a/Kernel/Arch/x86/common/Interrupts.cpp b/Kernel/Arch/x86/common/Interrupts.cpp index 0c2650ed9b..5cedb48388 100644 --- a/Kernel/Arch/x86/common/Interrupts.cpp +++ b/Kernel/Arch/x86/common/Interrupts.cpp @@ -215,10 +215,16 @@ static void dump(const RegisterState& regs) void handle_crash(RegisterState const& regs, char const* description, int signal, bool out_of_memory) { - if (!Process::has_current()) - PANIC("{} with !current", description); + auto* current_thread = Thread::current(); + if (!current_thread) + PANIC("{} with !Thread::current()", description); - auto& process = Process::current(); + if (!current_thread->should_ignore_signal(signal) && !current_thread->is_signal_masked(signal)) { + current_thread->send_urgent_signal_to_self(signal); + return; + } + + auto& process = current_thread->process(); // If a process crashed while inspecting another process, // make sure we switch back to the right page tables. @@ -316,7 +322,7 @@ void page_fault_handler(TrapFrame* trap) VirtualAddress userspace_sp = VirtualAddress { regs.userspace_sp() }; if (!faulted_in_kernel && !MM.validate_user_stack(current_thread->process().address_space(), userspace_sp)) { dbgln("Invalid stack pointer: {}", userspace_sp); - handle_crash(regs, "Bad stack on page fault", SIGSEGV); + 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) { @@ -417,7 +423,7 @@ void page_fault_handler(TrapFrame* trap) } } - handle_crash(regs, "Page Fault", SIGSEGV, response == PageFaultResponse::OutOfMemory); + return handle_crash(regs, "Page Fault", SIGSEGV, response == PageFaultResponse::OutOfMemory); } else if (response == PageFaultResponse::Continue) { dbgln_if(PAGE_FAULT_DEBUG, "Continuing after resolved page fault"); } else { diff --git a/Kernel/Memory/MemoryManager.cpp b/Kernel/Memory/MemoryManager.cpp index 42cd4e34f3..54b0adfb01 100644 --- a/Kernel/Memory/MemoryManager.cpp +++ b/Kernel/Memory/MemoryManager.cpp @@ -654,7 +654,7 @@ void MemoryManager::validate_syscall_preconditions(AddressSpace& space, Register VirtualAddress userspace_sp = VirtualAddress { regs.userspace_sp() }; if (!MM.validate_user_stack_no_lock(space, userspace_sp)) { dbgln("Invalid stack pointer: {}", userspace_sp); - unlock_and_handle_crash("Bad stack on syscall entry", SIGSEGV); + return unlock_and_handle_crash("Bad stack on syscall entry", SIGSEGV); } } @@ -663,17 +663,17 @@ void MemoryManager::validate_syscall_preconditions(AddressSpace& space, Register auto* calling_region = MM.find_user_region_from_vaddr_no_lock(space, ip); if (!calling_region) { dbgln("Syscall from {:p} which has no associated region", ip); - unlock_and_handle_crash("Syscall from unknown region", SIGSEGV); + return unlock_and_handle_crash("Syscall from unknown region", SIGSEGV); } if (calling_region->is_writable()) { dbgln("Syscall from writable memory at {:p}", ip); - unlock_and_handle_crash("Syscall from writable memory", SIGSEGV); + return unlock_and_handle_crash("Syscall from writable memory", SIGSEGV); } if (space.enforces_syscall_regions() && !calling_region->is_syscall_region()) { dbgln("Syscall from non-syscall region"); - unlock_and_handle_crash("Syscall from non-syscall region", SIGSEGV); + return unlock_and_handle_crash("Syscall from non-syscall region", SIGSEGV); } } } diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index ea4fc3a9a3..fef73d4e21 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -802,6 +802,12 @@ bool Thread::has_signal_handler(u8 signal) const return !action.handler_or_sigaction.is_null(); } +bool Thread::is_signal_masked(u8 signal) const +{ + VERIFY(signal < 32); + return (1 << (signal - 1)) & m_signal_mask; +} + bool Thread::has_alternative_signal_stack() const { return m_alternative_signal_stack_size != 0; diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 29a7bc784e..4e50c27c3d 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -1023,6 +1023,7 @@ public: [[nodiscard]] bool has_unmasked_pending_signals() const { return m_have_any_unmasked_pending_signals.load(AK::memory_order_consume); } [[nodiscard]] bool should_ignore_signal(u8 signal) const; [[nodiscard]] bool has_signal_handler(u8 signal) const; + [[nodiscard]] bool is_signal_masked(u8 signal) const; u32 pending_signals() const; u32 pending_signals_for_state() const; |