kernel: Allow sending signals to process groups from userspace
This commit is contained in:
parent
4d6c8aa8bf
commit
08583d5ad4
@ -54,16 +54,65 @@ Result<u64> sys_kill(Registers*, SyscallArgs args)
|
|||||||
pid_t pid = (pid_t)args[0];
|
pid_t pid = (pid_t)args[0];
|
||||||
int signo = (int)args[1];
|
int signo = (int)args[1];
|
||||||
|
|
||||||
// FIXME: Support this case.
|
auto send_signal = [&](Thread* target) -> Result<void> {
|
||||||
if (pid <= 0) return err(ENOTSUP);
|
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 {};
|
||||||
|
if (signo == 0) return {};
|
||||||
|
|
||||||
auto* target = TRY(Result<Thread*>::from_option(Scheduler::find_by_pid(pid), ESRCH));
|
target->send_signal(signo);
|
||||||
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 {};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
auto* target = TRY(Result<Thread*>::from_option(Scheduler::find_by_pid(pid), ESRCH));
|
||||||
|
TRY(send_signal(target));
|
||||||
|
}
|
||||||
|
else if (pid == 0)
|
||||||
|
{
|
||||||
|
int errno = -1;
|
||||||
|
bool pgid_exists = false;
|
||||||
|
Scheduler::for_each_in_process_group(current->pgid, [&](Thread* target) {
|
||||||
|
pgid_exists = true;
|
||||||
|
auto rc = send_signal(target);
|
||||||
|
if (rc.has_error())
|
||||||
|
{
|
||||||
|
errno = rc.error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (errno > 0) return err(errno);
|
||||||
|
if (!pgid_exists) return err(ESRCH);
|
||||||
|
}
|
||||||
|
else if (pid == -1)
|
||||||
|
{
|
||||||
|
for (auto* thread : g_threads)
|
||||||
|
{
|
||||||
|
// We ignore permission errors here.
|
||||||
|
if (thread != current && thread->id != 1) send_signal(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pid < -1)
|
||||||
|
{
|
||||||
|
int errno = -1;
|
||||||
|
bool pgid_exists = false;
|
||||||
|
Scheduler::for_each_in_process_group(-pid, [&](Thread* target) {
|
||||||
|
pgid_exists = true;
|
||||||
|
auto rc = send_signal(target);
|
||||||
|
if (rc.has_error())
|
||||||
|
{
|
||||||
|
errno = rc.error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (errno > 0) return err(errno);
|
||||||
|
if (!pgid_exists) return err(ESRCH);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user