From e14e919b78b9043fb026a3e5d03402cd38e9fa96 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Sat, 26 Feb 2022 15:29:31 +0330 Subject: [PATCH] Kernel: Fill some siginfo and ucontext fields on SA_SIGINFO There's no reason to fill in any of these fields if SA_SIGINFO is not given, as the signal handler won't be reading from them at all. --- Kernel/API/POSIX/ucontext.h | 1 + Kernel/Process.h | 1 + Kernel/Thread.cpp | 74 +++++++++++++++++++++++++++++++++---- Kernel/Thread.h | 1 + 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/Kernel/API/POSIX/ucontext.h b/Kernel/API/POSIX/ucontext.h index 306c41cac4..ef6836250b 100644 --- a/Kernel/API/POSIX/ucontext.h +++ b/Kernel/API/POSIX/ucontext.h @@ -54,6 +54,7 @@ typedef struct __ucontext { #define SI_TIMER 0x40000002 #define SI_ASYNCIO 0x40000003 #define SI_MESGQ 0x40000004 +#define SI_NOINFO 0x40000042 #ifdef __cplusplus } diff --git a/Kernel/Process.h b/Kernel/Process.h index 97300c5d66..560e7064b3 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -451,6 +451,7 @@ public: ErrorOr send_signal(u8 signal, Process* sender); u8 termination_signal() const { return m_protected_values.termination_signal; } + u8 termination_status() const { return m_protected_values.termination_status; } u16 thread_count() const { diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 837741fc50..0b97b7c2f3 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -738,6 +738,7 @@ void Thread::send_signal(u8 signal, [[maybe_unused]] Process* sender) } m_pending_signals |= 1 << (signal - 1); + m_signal_senders[signal] = sender ? sender->pid() : pid(); m_have_any_unmasked_pending_signals.store((pending_signals_for_state() & ~m_signal_mask) != 0, AK::memory_order_release); m_signal_blocker_set.unblock_all_blockers_whose_conditions_are_met(); @@ -983,6 +984,8 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal) } auto& action = m_process->m_signal_action_data[signal]; + auto sender_pid = m_signal_senders[signal]; + auto sender = Process::from_pid(sender_pid); if (!current_trap() && !action.handler_or_sigaction.is_null()) { // We're trying dispatch a handled signal to a user process that was scheduled @@ -1074,30 +1077,85 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal) .uc_link = nullptr, .uc_sigmask = old_signal_mask, .uc_stack = { - .ss_sp = nullptr, - .ss_flags = 0, - .ss_size = 0, + .ss_sp = bit_cast(stack), + .ss_flags = action.flags & SA_ONSTACK, + .ss_size = use_alternative_stack ? m_alternative_signal_stack_size : 0, }, .uc_mcontext = {}, }; copy_kernel_registers_into_ptrace_registers(static_cast(ucontext.uc_mcontext), state); + auto fill_signal_info_for_signal = [&](siginfo& signal_info) { + if (signal == SIGCHLD) { + if (!sender) { + signal_info.si_code = CLD_EXITED; + return; + } + auto const* thread = sender->thread_list().with([](auto& list) { return list.is_empty() ? nullptr : list.first(); }); + if (!thread) { + signal_info.si_code = CLD_EXITED; + return; + } + + switch (thread->m_state) { + case State::Dead: + if (sender->should_generate_coredump() && sender->is_dumpable()) { + signal_info.si_code = CLD_DUMPED; + signal_info.si_status = sender->termination_signal(); + return; + } + [[fallthrough]]; + case State::Dying: + if (sender->termination_signal() == 0) { + signal_info.si_code = CLD_EXITED; + signal_info.si_status = sender->termination_status(); + return; + } + signal_info.si_code = CLD_KILLED; + signal_info.si_status = sender->termination_signal(); + return; + case State::Runnable: + case State::Running: + case State::Blocked: + signal_info.si_code = CLD_CONTINUED; + return; + case State::Stopped: + signal_info.si_code = CLD_STOPPED; + return; + case State::Invalid: + // Something is wrong, but we're just an observer. + break; + } + } + + signal_info.si_code = SI_NOINFO; + }; + siginfo signal_info { .si_signo = signal, - .si_code = 0, // FIXME: Signal-specific value, fill this in. + // Filled in below by fill_signal_info_for_signal. + .si_code = 0, + // Set for SI_TIMER, we don't have the data here. .si_errno = 0, - // FIXME: Plumb sender information here. - .si_pid = 0, - .si_uid = 0, - // FIXME: Fill these in. + .si_pid = sender_pid.value(), + .si_uid = sender ? sender->uid().value() : 0, + // Set for SIGILL, SIGFPE, SIGSEGV and SIGBUS + // FIXME: We don't generate these signals in a way that can be handled. .si_addr = 0, + // Set for SIGCHLD. .si_status = 0, + // Set for SIGPOLL, we don't have SIGPOLL. .si_band = 0, + // Set for SI_QUEUE, SI_TIMER, SI_ASYNCIO and SI_MESGQ + // We do not generate any of these. .si_value = { .sival_int = 0, }, }; + if (action.flags & SA_SIGINFO) + fill_signal_info_for_signal(signal_info); + #if ARCH(I386) constexpr static FlatPtr thread_red_zone_size = 0; #elif ARCH(X86_64) diff --git a/Kernel/Thread.h b/Kernel/Thread.h index a0b5324300..38227f8135 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -1220,6 +1220,7 @@ private: VirtualAddress m_thread_specific_data; Optional m_thread_specific_range; Array, NSIG> m_signal_action_masks; + Array m_signal_senders; Blocker* m_blocker { nullptr }; Kernel::Mutex* m_blocking_mutex { nullptr }; u32 m_lock_requested_count { 0 };