Что происходит, когда пользователь без полномочий root посылает сигналы процессу пользователя root?

33

Меня интересует безопасность сигналов UNIX.

SIGKILLубьет процесс. Итак, что происходит, когда процесс, не являющийся пользователем root, отправляет сигнал процессу пользователя root? Процесс все еще выполняет обработчик сигнала?

Я следую принятому ответу (gollum's) и печатаю man capabilites, и я нахожу много вещей о ядре Linux. От man capabilities:

NAME

   capabilities - overview of Linux capabilities
DESCRIPTION

   For the purpose of performing permission checks, traditional UNIX
   implementations distinguish two categories of processes: privileged
   processes (whose effective user ID is 0, referred to as superuser or
   root), and unprivileged processes (whose effective UID is nonzero).
   Privileged processes bypass all kernel permission checks, while
   unprivileged processes are subject to full permission checking based
   on the process's credentials (usually: effective UID, effective GID,
   and supplementary group list).

   Starting with kernel 2.2, Linux divides the privileges traditionally
   associated with superuser into distinct units, known as capabilities,
   which can be independently enabled and disabled.  Capabilities are a
   per-thread attribute.
lovespring
источник
5
Помимо SIGKILL, что является особым случаем и полностью управляется ядром, сигналы являются просто запросом. Процесс получения может делать с ними все, что угодно.
chepner
3
@chepner Кроме SIGKILL и SIGSTOP ...
jlliagre
1
@chepner Процесс получения должен активно решить, что он хочет обработать сигнал. Если процесс приема не сделал этого, то множество сигналов по умолчанию уничтожат процесс точно так же, как и при поступлении SIGKILL. Первоначально SIGINT, SIGKILLи SIGTERMбудет иметь точно такой же эффект, единственное отличие состоит в том, что процесс получения может изменить это значение по умолчанию для некоторых из них.
Касперд

Ответы:

34

В Linux это зависит от возможностей файла.

Возьмите следующий простой mykill.cисточник:

#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;
}

построить это:

gcc -Wall mykill.c -o /tmp/mykill

Теперь как пользователь root запустите процесс сна в фоновом режиме:

root@horny:/root# /bin/sleep 3600 &
[1] 16098

Теперь, как обычный пользователь, попробуйте убить его:

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

Теперь как пользователь root измените /tmp/mykillпрописные буквы:

root@horny:/root# setcap cap_kill+ep /tmp/mykill

И попробуйте снова как обычный пользователь:

demouser@horny:/home/demouser$ /tmp/mykill -9 16098
successfully sent signal 9 to process 16098

Наконец, пожалуйста, удалите /tmp/mykillпо понятным причинам;)

Голлум
источник
3
Следуйте вашей подсказке, я
набираю
24

Ничего такого:

strace kill -HUP 1
[...]
kill(1, SIGHUP)    = -1 EPERM (Operation not permitted)
[...]
Хауке Лагинг
источник
1
Является ли этот вид безопасности уровнем ОС или жестко запрограммирован в обработчике сигналов пользователя?
lovespring
3
@lovespring Ядро не доставляет сигнал целевому процессу. Системный вызов возвращается с ошибкой и, кроме этого, игнорируется.
Хауке Лагинг
Это не так в целом. Это зависит от возможностей.
Голлум
1
@psmears да, но у других есть подобные понятия (например, «привилегии» для соляриса). Так что ответ «Ничего» однозначно неверен.
Голлум
1
@gollum: Это не совсем неправильно (в конце концов, это поведение по умолчанию во всех ОС семейства Unix, и единственно возможное во многих - включая, например, более старые ядра Linux), но вы правы, что оно неполное - но просто упомяну «возможности», не вдаваясь в подробности о том, где они поддерживаются, также неполны в вопросе об общем Unix :)
psmears
5

kill(2) Справочная страница объясняет:

Linux Notes

В разных версиях ядра Linux ввел разные правила для разрешений, необходимых для непривилегированного процесса для отправки сигнала другому процессу. В ядрах с 1.0 по 1.2.2 сигнал может быть отправлен, если эффективный идентификатор пользователя отправителя совпадает с идентификатором получателя или реальный идентификатор пользователя отправителя совпадает с идентификатором получателя. От ядра 1.2.3 до 1.3.77 сигнал может быть отправлен, если эффективный идентификатор пользователя отправителя совпадает с действительным или эффективным идентификатором пользователя получателя. Текущие правила, которые соответствуют POSIX.1-2001, были приняты в ядре 1.3.78.

jai_s
источник
1.3.78 чрезвычайно древняя история, как 1.3. даты с 1995 года или около того. 1.3 была серия разработки, ведущая до 2,0 (в 1996 году)
vonbrand
-1

сигнал будет нести, но владелец процесса принадлежит root. Таким образом, другой пользователь не имеет права прекратить процесс, поэтому вы получите проблему с ошибкой разрешения.

Завершение процесса возможно только в том случае, если вы владеете правом собственности на данный процесс.

Навин Дхарман
источник
Нет, sys_kill возвращает -1, и errno будет -EPERM.
Петер говорит восстановить Монику