suid-root não tem efeito

6

Um programa do apue .

#include "apue.h"
#include <fcntl.h>

int main(int argc, char *argv[])
{
    if(argc!=2)
        err_quit("usage: a.out <pathname>");

    if(access(argv[1], R_OK)<0)
        err_ret("access error for %s",argv[1]);
    else
        printf("read access OK\n");
    if (open(argv[1], O_RDONLY)) {
        err_ret("open error for %s", argv[1]);
    } else {
        printf("open for reading OK\n");
    }

    return 0;
}

Eu o compilei para um executável chamado 4-2 e mudei o proprietário e configurei o suid, essa é a saída de ls -l :

-rwsr-xr-x 1 root sinners 8490 Jan  7 18:50 4-2*

e /etc/shadow :

-rw------- 1 root root 421 Jan  4 01:29 /etc/shadow

Mas quando eu executo:

user% ./4-2 /etc/shadow 
access error for /etc/shadow: Permission denied
open error for /etc/shadow: Permission denied

Alguém pode explicar por que estou recebendo esses erros access e open ?

    
por sinners 07.01.2012 / 18:48

1 resposta

7

Citação de access() página de manual :

The check is done using the calling process's real UID and GID, rather than the effective IDs as is done when actually attempting an operation (e.g., open(2)) on the file. This allows set-user-ID programs to easily determine the invoking user's authority.

O bit set-user-ID torna o UID efetivo igual ao proprietário do arquivo, mas o ID do usuário real permanece inalterado (isto é, permanece como era antes de exec() ).

Você pode usar setreuid() para modificar o UID efetivo e o UID real do processo ou pode usar open() para determinar privilégios. Eu recomendo a segunda solução, especialmente porque você já chama open() de qualquer maneira. Você pode verificar se errno é igual a EPERM para descobrir se as permissões insuficientes foram o motivo pelo qual open() falhou.

A chamada para open() falha em seu código, porque você usa o valor de retorno de open() como a condição if. Eu acho que a chamada realmente é bem-sucedida e retorna um descritor de arquivo válido, diferente de zero (zero sendo usado por stdin), fazendo com que o controle entre na ramificação de tratamento de erros. A ramificação de tratamento de erros do if exibe a mensagem de erro EPERM , pois esse é o último erro que ocorreu devido à chamada access() . A condição para entrar na ramificação de tratamento de erros deve verificar se open() retornou -1.

    
por 07.01.2012 / 19:03