From c2e50547cc05cb2bb0c2546fce44e94380ee8780 Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 5 Sep 2024 16:24:18 -0300 Subject: [PATCH] signal: do auth check --- kernel-src/include/kernel/jobctl.h | 2 +- kernel-src/io/tty.c | 6 +++--- kernel-src/sys/defaultauth.c | 5 ----- kernel-src/sys/jobctl.c | 21 +++++++++++++++++---- kernel-src/sys/syscalls/kill.c | 24 ++++++++++++++++++------ 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/kernel-src/include/kernel/jobctl.h b/kernel-src/include/kernel/jobctl.h index 6e53ac73..19079779 100644 --- a/kernel-src/include/kernel/jobctl.h +++ b/kernel-src/include/kernel/jobctl.h @@ -13,7 +13,7 @@ pid_t jobctl_getpgid(proc_t *proc); pid_t jobctl_getsid(proc_t *proc); int jobctl_setctty(proc_t *proc, void *ctty, bool steal); void *jobctl_getctty(proc_t *proc); -int jobctl_signal(proc_t *proc, int signal); +int jobctl_signal(proc_t *proc, int signal, proc_t *sender); proc_t *jobctl_getforeground(proc_t *proc); int jobctl_setforeground(proc_t *session, proc_t *pgrp); diff --git a/kernel-src/io/tty.c b/kernel-src/io/tty.c index b06b7e05..528b8c8e 100644 --- a/kernel-src/io/tty.c +++ b/kernel-src/io/tty.c @@ -74,7 +74,7 @@ void tty_process(tty_t *tty, char c) { if (signal >= 0) { proc_t *pgrp = getforeground(tty); if (pgrp) { - jobctl_signal(pgrp, signal); + jobctl_signal(pgrp, signal, NULL); PROC_RELEASE(pgrp); } return; @@ -311,7 +311,7 @@ int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result, cred_t *cre proc_t *foreground = getforeground(tty); if (foreground) { - jobctl_signal(foreground, SIGWINCH); + jobctl_signal(foreground, SIGWINCH, NULL); PROC_RELEASE(foreground); } break; @@ -524,7 +524,7 @@ void tty_unregister(tty_t *tty) { proc_t *foreground = getforeground(tty); if (foreground) { - jobctl_signal(foreground, SIGHUP); + jobctl_signal(foreground, SIGHUP, NULL); PROC_RELEASE(foreground); } } diff --git a/kernel-src/sys/defaultauth.c b/kernel-src/sys/defaultauth.c index 2035013d..e6e49a65 100644 --- a/kernel-src/sys/defaultauth.c +++ b/kernel-src/sys/defaultauth.c @@ -249,7 +249,6 @@ static int credlistener(cred_t *cred, int actions, void *arg0, void *arg1, void static int process(cred_t *cred, int actions, void *arg0, void *arg1, void *arg2) { proc_t *proc = arg0; - int *signal = arg1; int weight = 0; if (actions & AUTH_ACTIONS_PROCESS_SIGNAL) { @@ -260,10 +259,6 @@ static int process(cred_t *cred, int actions, void *arg0, void *arg1, void *arg2 cred->euid == proc->cred.uid || cred->euid == proc->cred.suid) weight += 1; - else if (*signal == SIGCONT) { - // TODO SIGCONT is supposed to work on the same process group; we are being a bit more permissive here for now - weight += 1; - } DONE_CHECK(actions); } diff --git a/kernel-src/sys/jobctl.c b/kernel-src/sys/jobctl.c index 3af0872f..207c2059 100644 --- a/kernel-src/sys/jobctl.c +++ b/kernel-src/sys/jobctl.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -278,8 +279,8 @@ void jobctl_detach(proc_t *proc) { PROC_RELEASE(unholdsession); } else { jobctl_setctty(proc, NULL, 0); - jobctl_signal(foreground, SIGHUP); - jobctl_signal(foreground, SIGCONT); + jobctl_signal(foreground, SIGHUP, NULL); + jobctl_signal(foreground, SIGCONT, NULL); PROC_RELEASE(foreground); } } @@ -378,11 +379,13 @@ void jobctl_procremove(proc_t *proc) { // proc can be null if the signal is being sent to the calling processes own process group // since that is only passed from a userland thread, we can assume _cpu()->thread->proc is not null -int jobctl_signal(proc_t *proc, int signal) { +int jobctl_signal(proc_t *proc, int signal, proc_t *sender) { int error = 0; bool intstatus = interrupt_set(false); proc_t *leader; proc_t *tmpproc = _cpu()->thread->proc; + pid_t senderpgid = sender ? jobctl_getpgid(sender) : 0; + if (proc == NULL) { spinlock_acquire(&tmpproc->jobctllock); leader = tmpproc->pgrp.leader ? tmpproc->pgrp.leader : tmpproc; @@ -400,11 +403,21 @@ int jobctl_signal(proc_t *proc, int signal) { spinlock_acquire(&leader->pgrp.lock); + size_t donecount = 0; proc_t *iterator = leader; while (iterator) { - signal_signalproc(iterator, signal); + // only send the signal if: + // there isn't a specific sender (for example, ^C from the tty) + // the signal is SIGCONT and they are from the same process group + // the auth check passes + if (senderpgid == 0 || (signal == SIGCONT && leader->pid == senderpgid) || auth_process_check(&sender->cred, AUTH_ACTIONS_PROCESS_SIGNAL, iterator) == 0) { + signal_signalproc(iterator, signal); + ++donecount; + } + iterator = iterator->pgrp.nextmember; } + error = donecount == 0 ? EPERM : 0; spinlock_release(&leader->pgrp.lock); diff --git a/kernel-src/sys/syscalls/kill.c b/kernel-src/sys/syscalls/kill.c index d3ee3690..0b413a62 100644 --- a/kernel-src/sys/syscalls/kill.c +++ b/kernel-src/sys/syscalls/kill.c @@ -2,6 +2,7 @@ #include #include #include +#include syscallret_t syscall_kill(context_t *context, int pid, int signal) { syscallret_t ret = { @@ -30,16 +31,27 @@ syscallret_t syscall_kill(context_t *context, int pid, int signal) { return ret; } - if (pid >= 1) - signal_signalproc(target, signal); - else - ret.errno = jobctl_signal(target, signal); + // null signal is meant to find out about the existance of a process + if (signal == 0) + goto leave; + if (pid >= 1) { + if (signal != SIGCONT && jobctl_getpgid(target) != jobctl_getpgid(_cpu()->thread->proc)) { + ret.errno = auth_process_check(&_cpu()->thread->proc->cred, AUTH_ACTIONS_PROCESS_SIGNAL, target); + if (ret.errno) + goto leave; + } + + signal_signalproc(target, signal); + } else { + ret.errno = jobctl_signal(target, signal, _cpu()->thread->proc); + } + + leave: if (target) { PROC_RELEASE(target); } - ret.errno = 0; - ret.ret = 0; + ret.ret = ret.errno ? -1 : 0; return ret; }