#include "Log.h" #include "Pledge.h" #include "memory/MemoryManager.h" #include "sys/Syscall.h" #include "thread/Scheduler.h" #include Result sys_sigreturn(Registers* regs, SyscallArgs) { auto* current = Scheduler::current(); current->sigreturn(regs); // Since we could be returning to anywhere in the program, we don't want to be changing the return value register // (RAX on x86_64). But our syscall framework doesn't allow that, so we just set it to its current value. return current->return_register(); } Result sys_sigaction(Registers*, SyscallArgs args) { auto* current = Scheduler::current(); TRY(check_pledge(current, Promise::p_stdio)); int signo = (int)args[0]; const struct sigaction* act = (const struct sigaction*)args[1]; struct sigaction* oldact = (struct sigaction*)args[2]; void* sigreturn = (void*)args[3]; if (signo > NSIG) return err(EINVAL); if (signo <= 0) return err(EINVAL); if (oldact) { if (!MemoryManager::copy_to_user_typed(oldact, ¤t->signal_handlers[signo - 1])) return err(EFAULT); } if (act) { struct sigaction kact; if (!MemoryManager::copy_from_user_typed(act, &kact)) return err(EFAULT); kact.__sa_sigreturn = sigreturn; current->signal_handlers[signo - 1] = kact; } return 0; } Result sys_kill(Registers*, SyscallArgs args) { auto* current = Scheduler::current(); TRY(check_pledge(current, Promise::p_proc)); pid_t pid = (pid_t)args[0]; int signo = (int)args[1]; // FIXME: Support this case. if (pid <= 0) return err(ENOTSUP); auto* target = TRY(Result::from_option(Scheduler::find_by_pid(pid), ESRCH)); if (current->auth.euid != 0 && current->auth.euid != target->auth.euid && current->auth.egid != target->auth.egid) return err(EPERM); if (target->is_kernel) return 0; if (signo == 0) return 0; target->send_signal(signo); return 0; } Result sys_sigprocmask(Registers*, SyscallArgs args) { auto* current = Scheduler::current(); TRY(check_pledge(current, Promise::p_stdio)); int how = (int)args[0]; const sigset_t* set = (const sigset_t*)args[1]; sigset_t* oldset = (sigset_t*)args[2]; if (oldset) { sigset_t mask = current->signal_mask.value(); if (!MemoryManager::copy_to_user_typed(oldset, &mask)) return err(EFAULT); } if (set) { sigset_t kset; if (!MemoryManager::copy_from_user_typed(set, &kset)) return err(EFAULT); switch (how) { case SIG_BLOCK: current->signal_mask = current->signal_mask.value() | kset; break; case SIG_UNBLOCK: current->signal_mask = current->signal_mask.value() & ~kset; break; case SIG_SETMASK: current->signal_mask = kset; break; default: return err(EINVAL); } } return 0; }