Dentro do fakeroot, por que o chown retorna o EPERM mesmo que tenha sucesso (mas novamente não)?

3

Eu tenho tido um comportamento bizarro ao usar chown (2) dentro de um ambiente de fakeroot. O programa mínimo a seguir ilustra o problema:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>

int main() {
    //choose a reasonably unique filename
    char path[30];
    sprintf(path, "./file-%d", getpid());

    //create file
    close(creat(path, 0644));

    //chown to some random UID/GID
    chown(path, 4444, 4444);

    //stat again (result can be seen in strace below)
    struct stat s;
    stat(path, &s);

    return 0;
}

Suponha que seja main.c . Agora eu corro o seguinte dentro de um fakeroot bash :

$ gcc -o main main.c
$ strace -v ./main
...
creat("./file-10872", 0644)             = 3
close(3)                                = 0
...
lchown("./file-10872", 84, 84)          = -1 EPERM (Operation not permitted)
stat("./file-10872", {st_dev=makedev(8, 3), st_ino=3932971, st_mode=S_IFREG|0644, st_nlink=1, st_uid=1001, st_gid=100, st_blksize=4096, st_blocks=0, st_size=0, st_atime=2015/10/31-20:12:07, st_mtime=2015/10/31-20:12:07, st_ctime=2015/10/31-20:12:07}) = 0
...
$ ls -l file-10872
-rw-r--r-- 1 4444 4444 0 31. Okt 20:12 file-10872

O que podemos ver aqui?

  1. A chamada chown falhou com EPERM (Operação não permitida).
  2. O stat subseqüente mostra st_uid=1001, st_gid=100 , que é meu UID e GID reais (não falsos) (o que é estranho porque, se eu entender o fakeroot corretamente, ele deve mostrar pelo menos st_uid=0, st_gid=0 ).
  3. O ls -l subseqüente no mesmo arquivo mostra que a chown SUCCEEDED, embora chown tenha relatado falha, e o stat subsequente confirmou isso.

O que diabos está acontecendo aqui? Eu encontrei um bug no fakeroot, ou isso é apenas um mal-entendido de como funciona o fakeroot?

(Meu fakeroot é a versão 1.20.2 e meu sistema é o Arch Linux com todas as atualizações.)

Atualização: Foi corretamente apontado por Jonas Wielicki que o strace funciona no nível syscall e, portanto, é enganoso, pois os resultados do syscalls serão mutilados pelo libfakeroot antes de serem retornados ao próprio programa . Acontece que depois de stat(path, &s) , o struct stat s contém o novo UID e GID. Mas ainda está confuso que chown falha com o EPERM.

    
por Stefan Majewsky 31.10.2015 / 20:23

1 resposta

5

chown na verdade retorna zero quando executado em fakeroot . Assim, de acordo com errno(3) :

Its value is significant only when the return value of the call indicated an error (i.e., -1 from most system calls; -1 or NULL from most library functions); a function that succeeds is allowed to change errno.

O valor em errno não é significativo e chown na verdade não falha.

Como já discutido nos comentários, a saída strace contém EPIDs e lances / gids não falsificados conforme esperado, pois strace está abaixo da biblioteca fakeroot LD_PRELOAD . Imprimir o uid / gid do programa mostra a saída correta (falsificada).

    
por 31.10.2015 / 21:00