Kernel: Fix signal related syscalls

There were missing locks, out of order sigprocmask, incorrect signal
masking...
This commit is contained in:
2026-04-05 02:31:30 +03:00
parent 8ca3c5d778
commit 1e3ca7dc18

View File

@@ -3047,7 +3047,7 @@ namespace Kernel
TRY(read_from_user(user_act, &new_act, sizeof(struct sigaction))); TRY(read_from_user(user_act, &new_act, sizeof(struct sigaction)));
{ {
SpinLockGuard signal_lock_guard(m_signal_lock); SpinLockGuard _(m_signal_lock);
old_act = m_signal_handlers[signal]; old_act = m_signal_handlers[signal];
if (user_act != nullptr) if (user_act != nullptr)
m_signal_handlers[signal] = new_act; m_signal_handlers[signal] = new_act;
@@ -3061,7 +3061,14 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_sigpending(sigset_t* user_sigset) BAN::ErrorOr<long> Process::sys_sigpending(sigset_t* user_sigset)
{ {
const sigset_t sigset = (signal_pending_mask() | Thread::current().m_signal_pending_mask) & Thread::current().m_signal_block_mask; sigset_t sigset;
{
auto& thread = Thread::current();
SpinLockGuard _(thread.m_signal_lock);
sigset = (signal_pending_mask() | thread.m_signal_pending_mask) & thread.m_signal_block_mask;
}
TRY(write_to_user(user_sigset, &sigset, sizeof(sigset_t))); TRY(write_to_user(user_sigset, &sigset, sizeof(sigset_t)));
return 0; return 0;
} }
@@ -3070,34 +3077,36 @@ namespace Kernel
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
if (user_oset != nullptr) auto& thread = Thread::current();
{
const sigset_t current = Thread::current().m_signal_block_mask; const sigset_t old_sigset = thread.m_signal_block_mask;
TRY(write_to_user(user_oset, &current, sizeof(sigset_t)));
}
if (user_set != nullptr) if (user_set != nullptr)
{ {
sigset_t set; sigset_t mask;
TRY(read_from_user(user_set, &set, sizeof(sigset_t))); TRY(read_from_user(user_set, &mask, sizeof(sigset_t)));
mask &= ~((1ull << SIGKILL) | (1ull << SIGSTOP));
const sigset_t mask = set & ~(SIGKILL | SIGSTOP); SpinLockGuard _(thread.m_signal_lock);
switch (how) switch (how)
{ {
case SIG_BLOCK: case SIG_BLOCK:
Thread::current().m_signal_block_mask |= mask; thread.m_signal_block_mask |= mask;
break;
case SIG_SETMASK:
Thread::current().m_signal_block_mask = mask;
break; break;
case SIG_UNBLOCK: case SIG_UNBLOCK:
Thread::current().m_signal_block_mask &= ~mask; thread.m_signal_block_mask &= ~mask;
break;
case SIG_SETMASK:
thread.m_signal_block_mask = mask;
break; break;
default: default:
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }
} }
if (user_oset != nullptr)
TRY(write_to_user(user_oset, &old_sigset, sizeof(sigset_t)));
return 0; return 0;
} }
@@ -3109,7 +3118,7 @@ namespace Kernel
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
auto& thread = Thread::current(); auto& thread = Thread::current();
thread.set_suspend_signal_mask(set & ~(SIGKILL | SIGSTOP)); thread.set_suspend_signal_mask(set & ~((1ull << SIGKILL) | (1ull << SIGSTOP)));
// FIXME: i *think* here is a race condition as kill doesnt hold process lock // FIXME: i *think* here is a race condition as kill doesnt hold process lock
while (!thread.is_interrupted_by_signal()) while (!thread.is_interrupted_by_signal())