Participação em grupos e processos setuid / setgid

10

Processos que diminuem os privilégios via setuid()e setgid()parecem não herdar as associações de grupo do uid / gid que eles definem.

Eu tenho um processo de servidor que deve ser executado como root para abrir uma porta privilegiada; depois disso, ele é redimensionado para um uid / gid não privilegiado específico, 1 - por exemplo, o do usuário foo(UID 73). O usuário fooé um membro do grupo bar:

> cat /etc/group | grep bar
bar:x:54:foo

Portanto, se eu entrar como foo, posso ler um arquivo /test.txtcom estas características:

> ls -l /test.txt
-rw-r----- 1 root bar 10 Mar  8 16:22 /test.txt

No entanto, o seguinte programa C (compilação std=gnu99), quando executado root:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main (void) {
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}   

Sempre relata Permissão negada . Eu imagino que isso tenha a ver com ser um processo sem logon, mas meio que prejudica a maneira como as permissões devem funcionar.


1. O que geralmente é SOP para servidores, e acho que deve haver uma maneira de contornar isso, pois encontrei um relatório de alguém fazendo o apache - o apache foi adicionado ao grupo de áudio e, aparentemente, pode usar o sistema de som. Obviamente, isso provavelmente acontece em um fork e não no processo original, mas, na verdade, o caso é o mesmo no meu contexto (é um processo filho bifurcado após a chamada setuid).

Cachinhos Dourados
fonte
Alterne as setuid()/ setgid()chamadas.
vonbrand
@vonbrand ROTFL Eu pensei que estava em um facepalm lá - mas mesmo resultado, então eu vou editar a pergunta para eliminar o arenque vermelho.
8115 goldilocks
1
Se você usar em setgid(54)vez de setgid(73)(como em /etc/groups, group barhas gid 54), isso funciona?
precisa saber é o seguinte
@lgeorget Claro, mas isso anula o objetivo. O processo precisa de seu próprio GID por outros motivos e, da mesma forma, esses arquivos devem ter as permissões que possuem. É por isso que a participação em grupos no plural é necessária - por exemplo, e se você tiver dois usuários que precisam fazer isso. Note que você não pode setuid()novamente depois de fazê-lo ... mas, hmmm ... Eu acho que você pode com seteuid()...
Goldilocks
1
Minha pergunta era ter certeza de que não havia outro problema sutil oculto em algum lugar. :-)
lgeorget

Respostas:

14

O problema é esse setuide setgid não é suficiente para fornecer ao seu processo todas as credenciais necessárias. As autorizações de um processo dependem de

  • seu UID
  • seu GID
  • seus grupos suplementares
  • suas capacidades.

Veja man 7 credentialspara obter uma visão geral mais detalhada. Portanto, no seu caso, o problema é que você definiu corretamente o UID e o GID, mas não definiu os grupos suplementares do processo. E o grupo bartem GID 54, não 73, portanto não é reconhecido como um grupo em que seu processo está.

Você deveria fazer

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <grp.h>

int main (void) {
    gid_t supplementary_groups[] = {54};

    setgroups(1, supplementary_groups);
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}  
lgeorget
fonte
1
Essa foi uma pergunta interessante que merece mais votos, porque poderia realmente ser útil para muitas pessoas por aí. :-)
lgeorget
Então, eu estava tendo um problema semelhante com portas seriais. Eu implementei isso para o dialoutgrupo e funcionou pela primeira vez.
tl8
0

OK, arrastei um pouco pela rede. Primeiro pensei que o APUE continha todas as respostas, mas estava enganado. E minha cópia (edição antiga) está em funcionamento, então ... O capítulo 5 do Manual de Administração para Unix e Linux parece promissor, mas não o tenho (apenas uma cópia das duas primeiras edições, também em funcionamento).

Os poucos recursos que encontrei (google para "daemon writing unix") falam sobre etapas importantes, como dissociar o tty, etc. Mas nada sobre o UID / GID. Estranhamente, nem mesmo a extensa coleção HOWTO em http://tldp.org parece ter detalhes. Apenas excetion é de Jason Curto Vamos escrever uma Daemon Linux - parte I . Detalhes completos de como o SUID / SGID e toda essa bagunça funcionam são os desmistificados de Chen, Wagner e Dean (um artigo no USENIX 2002). Mas tenha cuidado, o Linux possui um UID extra, o FSUID (consulte Notas de incompatibilidade do Unol de Wolter : funções de configuração do UID para uma discussão).

Demonstrar um processo definitivamente não é para os fracos de coração. Considerações gerais de segurança são fornecidas no HOWTO da D. Wheeler Secure Programming para Linux e Unix - Criando software seguro . O Systemd promete simplificar a maior parte disso (e, assim, reduzir o espaço para erros que levam a problemas de segurança), consulte o manual do daemon .

vonbrand
fonte
1
A questão não é sobre daemonização. Você confundiu o bit SUID (concedendo a um processo as permissões do proprietário do executável) setuid(), o que permite que o processo altere seu UID arbitrariamente. Geralmente, o SUID destina-se a permitir uma escalada de permissões (sem privilégios -> privilegados), ao passo que setuid()só pode fazer o contrário.
Goldilocks