O que acontece quando um usuário não root envia sinais para o processo do usuário root?

33

Eu estou pensando sobre a segurança dos sinais UNIX.

SIGKILLvai matar o processo. Então, o que acontece quando o processo de um usuário não root envia um sinal para o processo de um usuário root? O processo ainda executa o manipulador de sinal?

Sigo a resposta aceita (gollum's), digito man capabilitese encontro muitas coisas sobre o kernel do Linux. De 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
fonte
5
Fora isso SIGKILL, que é um caso especial e gerenciado completamente pelo kernel, os sinais são apenas uma solicitação. O processo de recebimento pode fazer o que eles quiserem com eles.
chepner
3
@chepner Outros que SIGKILL e SIGSTOP ...
jlliagre
1
@chepner O processo de recebimento deve decidir ativamente que deseja lidar com o sinal. Se o processo de recebimento não o tiver feito, muitos sinais, por padrão, eliminarão o processo exatamente da mesma maneira que o SIGKILLfaria. Inicialmente SIGINT, SIGKILLe SIGTERMterá exatamente o mesmo efeito, a única diferença é que o processo de recebimento pode alterar esse padrão para alguns deles.
kasperd

Respostas:

34

No Linux, isso depende dos recursos do arquivo.

Pegue a seguinte mykill.cfonte simples :

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

construa:

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

Agora, como usuário root, inicie um processo de suspensão em segundo plano:

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

Agora, como usuário normal, tente matá-lo:

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

Agora, como usuário root, altere os /tmp/mykilllimites:

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

E tente novamente como usuário normal:

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

Finalmente, exclua /tmp/mykillpor razões óbvias;)

gollum
fonte
3
Siga sua pista, digito "man capacidades" e encontro muitas coisas sobre o kernel do linux
lovespring
24

Nada:

strace kill -HUP 1
[...]
kill(1, SIGHUP)    = -1 EPERM (Operation not permitted)
[...]
Hauke ​​Laging
fonte
1
Esse tipo de segurança é feito pelo nível do sistema operacional ou codificado no manipulador de sinais do usuário?
lovespring
3
@lovespring O kernel não envia o sinal para o processo de destino. O syscall é retornado com um erro e, além disso, é ignorado.
Hauke ​​Laging
Isso não é verdade em geral. Depende dos recursos.
Gollum
1
@psmears sim, mas outros têm conceitos semelhantes (por exemplo, "privilégios" no solaris). Portanto, a resposta "Nada" está definitivamente errada.
Gollum
1
@gollum: Não é exatamente errado (afinal, é o comportamento padrão em todos os sistemas operacionais da família Unix e o único possível em muitos - incluindo kernels Linux mais antigos, por exemplo), mas você está certo que está incompleto - mas apenas mencionando "capacidades", sem entrar em mais detalhes sobre onde eles estão suported também é incompleta em uma pergunta sobre Unix geral :)
psmears
5

kill(2) A página de manual explica:

Notas do Linux

Em diferentes versões do kernel, o Linux impôs regras diferentes para as permissões necessárias para um processo sem privilégios para enviar um sinal para outro processo. Nos kernels 1.0 a 1.2.2, um sinal pode ser enviado se o ID do usuário efetivo do remetente corresponder ao do destinatário ou o ID do usuário real do remetente corresponder ao do receptor. Do kernel 1.2.3 até 1.3.77, um sinal pode ser enviado se o ID do usuário efetivo do remetente corresponder ao ID do usuário real ou efetivo do receptor. As regras atuais, que estão em conformidade com POSIX.1-2001, foram adotadas no kernel 1.3.78.

jai_s
fonte
1.3.78 é uma história extremamente antiga, como 1.3. data de 1995 ou por aí. 1.3 foi a série de desenvolvimento anterior a 2.0 (em 1996)
vonbrand
-1

o sinal seria carregado, mas o proprietário do processo pertence à raiz. portanto, o outro usuário não tem o direito de encerrar o processo, para que você receba um problema de erro de permissão.

encerrar o processo só é possível quando você possui a propriedade (direitos adequados) do processo.

Naveen Dharman
fonte
Não, sys_kill devolve -1 e errno será -EPERM.
peterh diz restabelecer Monica