69 lines
2.0 KiB
C++
69 lines
2.0 KiB
C++
|
#include "Log.h"
|
||
|
#include "memory/MemoryManager.h"
|
||
|
#include "sys/Syscall.h"
|
||
|
#include "thread/Scheduler.h"
|
||
|
|
||
|
Result<u64> 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<u64> sys_sigaction(Registers*, SyscallArgs args)
|
||
|
{
|
||
|
auto* current = Scheduler::current();
|
||
|
|
||
|
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;
|
||
|
|
||
|
kinfoln("sigaction: installing signal handler for signo=%d: handler=%p, sigreturn=%p", signo,
|
||
|
(void*)kact.sa_handler, sigreturn);
|
||
|
|
||
|
current->signal_handlers[signo - 1] = kact;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Result<u64> sys_kill(Registers*, SyscallArgs args)
|
||
|
{
|
||
|
auto* current = Scheduler::current();
|
||
|
|
||
|
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<Thread*>::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->pending_signals |= 1 << (signo - 1);
|
||
|
|
||
|
return 0;
|
||
|
}
|