Kernel: Fix signal related syscalls
There were missing locks, out of order sigprocmask, incorrect signal masking...
This commit is contained in:
@@ -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, ¤t, 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())
|
||||||
|
|||||||
Reference in New Issue
Block a user