diff --git a/Kernel/Process.h b/Kernel/Process.h index 13140665bdd..d663448dd39 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -279,7 +279,7 @@ public: KResultOr sys$fork(RegisterState&); KResultOr sys$execve(Userspace); KResultOr sys$dup2(int old_fd, int new_fd); - KResultOr sys$sigaction(int signum, const sigaction* act, sigaction* old_act); + KResultOr sys$sigaction(int signum, Userspace act, Userspace old_act); KResultOr sys$sigprocmask(int how, Userspace set, Userspace old_set); KResultOr sys$sigpending(Userspace); KResultOr sys$getgroups(ssize_t, Userspace); diff --git a/Kernel/Syscalls/sigaction.cpp b/Kernel/Syscalls/sigaction.cpp index dcd875d087e..cd59d444779 100644 --- a/Kernel/Syscalls/sigaction.cpp +++ b/Kernel/Syscalls/sigaction.cpp @@ -69,23 +69,27 @@ KResultOr Process::sys$sigpending(Userspace set) return 0; } -KResultOr Process::sys$sigaction(int signum, const sigaction* act, sigaction* old_act) +KResultOr Process::sys$sigaction(int signum, Userspace user_act, Userspace user_old_act) { REQUIRE_PROMISE(sigaction); if (signum < 1 || signum >= 32 || signum == SIGKILL || signum == SIGSTOP) return EINVAL; + + sigaction act {}; + if (!copy_from_user(&act, user_act)) + return EFAULT; + InterruptDisabler disabler; // FIXME: This should use a narrower lock. Maybe a way to ignore signals temporarily? auto& action = Thread::current()->m_signal_action_data[signum]; - if (old_act) { - if (!copy_to_user(&old_act->sa_flags, &action.flags)) - return EFAULT; - if (!copy_to_user(&old_act->sa_sigaction, &action.handler_or_sigaction, sizeof(action.handler_or_sigaction))) + if (user_old_act) { + sigaction old_act {}; + old_act.sa_flags = action.flags; + old_act.sa_sigaction = reinterpret_cast(action.handler_or_sigaction.as_ptr()); + if (!copy_to_user(user_old_act, &old_act)) return EFAULT; } - if (!copy_from_user(&action.flags, &act->sa_flags)) - return EFAULT; - if (!copy_from_user(&action.handler_or_sigaction, &act->sa_sigaction, sizeof(action.handler_or_sigaction))) - return EFAULT; + action.flags = act.sa_flags; + action.handler_or_sigaction = VirtualAddress { reinterpret_cast(act.sa_sigaction) }; return 0; }