What happens when a non-root user sends signals to root user's process?
On Linux it depends on the file capabilities.
Take the following simple mykill.c
source:
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
void exit_usage(const char *prog) {
printf("usage: %s -<signal> <pid>\n", prog);
exit(1);
}
int main(int argc, char **argv) {
pid_t pid;
int sig;
if (argc != 3)
exit_usage(argv[0]);
sig = atoi(argv[1]);
pid = atoi(argv[2]);
if (sig >= 0 || pid < 2)
exit_usage(argv[0]);
if (kill(pid, -sig) == -1) {
perror("failed");
return 1;
}
printf("successfully sent signal %d to process %d\n", -sig, pid);
return 0;
}
build it:
gcc -Wall mykill.c -o /tmp/mykill
Now as user root start a sleep process in background:
root@horny:/root# /bin/sleep 3600 &
[1] 16098
Now as normal user try to kill it:
demouser@horny:/home/demouser$ ps aux | grep sleep
root 16098 0.0 0.0 11652 696 pts/20 S 15:06 0:00 sleep 500
demouser@horny:/home/demouser$ /tmp/mykill -9 16098
failed: Operation not permitted
Now as root user change the /tmp/mykill
caps:
root@horny:/root# setcap cap_kill+ep /tmp/mykill
And try again as normal user:
demouser@horny:/home/demouser$ /tmp/mykill -9 16098
successfully sent signal 9 to process 16098
Finally please delete /tmp/mykill
for obvious reasons ;)
Nothing:
strace kill -HUP 1
[...]
kill(1, SIGHUP) = -1 EPERM (Operation not permitted)
[...]
kill(2)
man page explains:
Linux Notes
Across different kernel versions, Linux has enforced different rules for the permissions required for an unprivileged process to send a signal to another process. In kernels 1.0 to 1.2.2, a signal could be sent if the effective user ID of the sender matched that of the receiver, or the real user ID of the sender matched that of the receiver. From kernel 1.2.3 until 1.3.77, a signal could be sent if the effective user ID of the sender matched either the real or effective user ID of the receiver. The current rules, which conform to POSIX.1-2001, were adopted in kernel 1.3.78.