Was passiert, wenn ein Benutzer ohne Rootberechtigung Signale an den Prozess des Rootberechtigten sendet?

33

Ich frage mich über die Sicherheit von UNIX-Signalen.

SIGKILLbricht den Prozess ab. Was passiert also, wenn ein Nicht-Root-Benutzer ein Signal an den Prozess eines Root-Benutzers sendet? Führt der Prozess den Signalhandler noch aus?

Ich folge der akzeptierten Antwort (gollum's), tippe man capabilitesund finde viele Dinge über den Linux-Kernel. Von 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.
Liebesfeder
quelle
5
Anders als SIGKILL, was ein Sonderfall ist und vollständig vom Kernel verwaltet wird, sind Signale lediglich eine Anfrage. Der Empfangsprozess kann mit ihnen alles machen, was sie wollen.
Chepner
3
@chepner Anders als SIGKILL und SIGSTOP ...
jlliagre
1
@chepner Der Empfangsprozess muss aktiv entscheiden, dass er das Signal verarbeiten möchte. Wenn der empfangende Prozess dies nicht getan hat, wird der Prozess von vielen Signalen standardmäßig genauso SIGKILLabgebrochen. Am Anfang SIGINT, SIGKILLund SIGTERMwird genau die gleiche Wirkung hat, ist der einzige Unterschied , dass der Empfangsprozess für einige von ihnen diese Standardeinstellung ändern.
Kasperd

Antworten:

34

Unter Linux hängt es von den Dateifunktionen ab.

Nehmen Sie die folgende einfache mykill.cQuelle:

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

baue es:

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

Starten Sie nun als Benutzer root einen Sleep-Prozess im Hintergrund:

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

Jetzt als normaler Benutzer versuchen, es zu töten:

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

Ändern Sie nun als Root-Benutzer die /tmp/mykillCaps:

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

Und versuchen Sie es als normaler Benutzer erneut:

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

Zum Schluss bitte /tmp/mykillaus offensichtlichen Gründen streichen ;)

Gollum
quelle
3
Folgen Sie Ihrem Hinweis, ich
tippe "Mannfähigkeiten
24

Nichts:

strace kill -HUP 1
[...]
kill(1, SIGHUP)    = -1 EPERM (Operation not permitted)
[...]
Hauke ​​Laging
quelle
1
Wird diese Art von Sicherheit von der Betriebssystemebene ausgeführt oder im Signalhandler des Benutzers fest codiert?
lovespring
3
@lovespring Der Kernel liefert das Signal nicht an den Zielprozess. Der Syscall wird mit einem Fehler zurückgegeben und ansonsten ignoriert.
Hauke ​​Laging
Das ist im Allgemeinen nicht wahr. Das hängt von den Fähigkeiten ab.
Gollum
1
@psmears ja, aber andere haben ähnliche Konzepte (z. B. "Privilegien" auf Solaris). Die Antwort "Nothing" ist also definitiv falsch.
Gollum
1
@gollum: Es ist nicht gerade falsch (schließlich ist es das Standardverhalten aller Betriebssysteme der Unix-Familie und das einzige, das unter vielen Betriebssystemen möglich ist - einschließlich älterer Linux-Kernel), aber Sie haben Recht, dass es unvollständig ist - erwähnen Sie es nur "Fähigkeiten", ohne näher darauf einzugehen, wo sie unterstützt werden, sind auch in einer Frage zu allgemeinem Unix unvollständig :)
psmears
5

kill(2) Manpage erklärt:

Linux-Notizen

In verschiedenen Kernelversionen hat Linux unterschiedliche Regeln für die Berechtigungen festgelegt, die erforderlich sind, damit ein nicht privilegierter Prozess ein Signal an einen anderen Prozess sendet. In den Kerneln 1.0 bis 1.2.2 könnte ein Signal gesendet werden, wenn die effektive Benutzer-ID des Absenders mit der des Empfängers übereinstimmt oder die tatsächliche Benutzer-ID des Absenders mit der des Empfängers übereinstimmt. Von Kernel 1.2.3 bis 1.3.77 konnte ein Signal gesendet werden, wenn die effektive Benutzer-ID des Absenders entweder mit der tatsächlichen oder der effektiven Benutzer-ID des Empfängers übereinstimmte. Die aktuellen Regeln, die POSIX.1-2001 entsprechen, wurden in Kernel 1.3.78 übernommen.

jai_s
quelle
1.3.78 ist extrem alte Geschichte, wie 1.3. stammt aus dem Jahr 1995 oder so. 1.3 war die Entwicklungsserie bis 2.0 (1996)
vonbrand
-1

das Signal würde tragen, aber der Prozessbesitzer gehört zu root. Daher hat der andere Benutzer nicht das Recht, den Vorgang zu beenden, sodass Sie ein Berechtigungsfehlerproblem erhalten.

Das Beenden eines Prozesses ist nur möglich, wenn Sie das Eigentum (die entsprechenden Rechte) an dem Prozess besitzen.

Naveen Dharman
quelle
Nein, sys_kill gibt -1 zurück und errno wird -EPERM sein.
Peter sagt wieder Monica