Co się stanie, gdy użytkownik inny niż root wyśle ​​sygnały do ​​procesu użytkownika root?

33

Zastanawiam się nad bezpieczeństwem sygnałów UNIX.

SIGKILLzabije proces. Co się stanie, gdy proces użytkownika innego niż root wyśle ​​sygnał do procesu użytkownika root? Czy proces nadal wykonuje procedurę obsługi sygnału?

Śledzę przyjętą odpowiedź (gollum) i piszę man capabilites, i znajduję wiele rzeczy na temat jądra Linuksa. Od 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.
uwielbia wiosnę
źródło
5
Poza tym SIGKILL, co jest szczególnym przypadkiem i całkowicie zarządzanym przez jądro, sygnały są jedynie żądaniem. Proces otrzymywania może z nimi zrobić, co tylko zechce.
chepner
3
@chepner Inne niż SIGKILL i SIGSTOP ...
jlliagre 30.01.16
1
@chepner Proces odbioru musi aktywnie zdecydować, że chce obsłużyć sygnał. Jeśli proces odbierania tego nie zrobił, wówczas wiele sygnałów domyślnie zabiłoby proces w dokładnie ten sam sposób SIGKILL. Początkowo SIGINT, SIGKILLi SIGTERMbędzie miał dokładnie taki sam efekt, jedyną różnicą jest to, że proces odbierania może zmienić to ustawienie domyślne dla niektórych z nich.
kasperd

Odpowiedzi:

34

W systemie Linux zależy to od możliwości plików.

Weź następujące proste mykill.cźródło:

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

Zbuduj to:

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

Teraz jako użytkownik root rozpocznij proces uśpienia w tle:

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

Teraz, jak zwykły użytkownik, spróbuj go zabić:

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

Teraz jako użytkownik root zmień /tmp/mykillwielkie litery:

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

I spróbuj ponownie jako zwykły użytkownik:

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

Na koniec proszę usunąć /tmp/mykillz oczywistych powodów;)

gollum
źródło
3
Podążaj za wskazówkami, piszę „zdolności man” i znajduję wiele rzeczy na temat jądra Linuksa
lovespring 29.01.16
24

Nic:

strace kill -HUP 1
[...]
kill(1, SIGHUP)    = -1 EPERM (Operation not permitted)
[...]
Hauke ​​Laging
źródło
1
Czy tego rodzaju zabezpieczenia są wykonywane przez poziom systemu operacyjnego lub są zakodowane na stałe w module obsługi sygnałów użytkownika?
lovespring 29.01.16
3
@lovespring Jądro nie dostarcza sygnału do procesu docelowego. Syscall jest zwracany z błędem i poza tym ignorowany.
Hauke ​​Laging
To ogólnie nie jest prawda. To zależy od możliwości.
gollum
1
@psmears tak, ale inni mają podobne koncepcje (np. „przywileje” w solaris). Zatem odpowiedź „Nic” jest zdecydowanie błędna.
gollum
1
@gollum: Nie jest to całkowicie złe (w końcu jest to domyślne zachowanie we wszystkich systemach operacyjnych z rodziny Unix i jedyne możliwe w wielu - w tym na przykład w starszych jądrach Linuksa), ale masz rację, że jest niekompletne - ale tylko wspomina „możliwości” Nie wdając się w szczegóły o tym, gdzie są one suported jest niekompletny w pytaniu o ogólnym Unix :)
psmears
5

kill(2) strona podręcznika wyjaśnia:

Uwagi na temat systemu Linux

W różnych wersjach jądra Linux wymusił różne reguły dotyczące uprawnień wymaganych dla nieuprzywilejowanego procesu wysyłania sygnału do innego procesu. W jądrach od 1.0 do 1.2.2 sygnał może zostać wysłany, jeśli efektywny identyfikator użytkownika nadawcy jest zgodny z identyfikatorem odbiorcy lub rzeczywisty identyfikator użytkownika nadawcy odpowiada identyfikatorowi odbiorcy. Od jądra 1.2.3 do 1.3.77 sygnał może być wysyłany, jeśli efektywny identyfikator użytkownika nadawcy odpowiada rzeczywistemu lub efektywnemu identyfikatorowi użytkownika odbiorcy. Obecne reguły, które są zgodne z POSIX.1-2001, zostały przyjęte w jądrze 1.3.78.

jai_s
źródło
1.3.78 to niezwykle stara historia, podobnie jak 1.3. pochodzi z 1995 roku lub później. 1.3 była serią rozwojową prowadzącą do 2.0 (w 1996 r.)
vonbrand 30.01.2016
-1

sygnał byłby przenoszony, ale właściciel procesu należy do katalogu głównego. więc drugi użytkownik nie ma prawa zakończyć procesu, więc pojawi się problem z błędem uprawnień.

zakończenie procesu jest możliwe tylko wtedy, gdy posiadasz własność (odpowiednie prawa) procesu.

Naveen Dharman
źródło
Nie, sys_kill zwraca -1, a errno ma wartość -EPERM.
peterh mówi o przywróceniu Moniki