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

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

Tenho tido um comportamento bizarro ao usarchown(2)dentro de um ambiente fakeroot. O seguinte programa mínimo 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 executo 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 chownchamada falhou com EPERM (Operação Não Permitida).
  2. O subseqüente statmostra st_uid=1001, st_gid=100qual é meu UID e GID reais (não falsos) (o que é estranho porque, se entendi o fakeroot corretamente, ele deveria pelo menos mostrar st_uid=0, st_gid=0).
  3. O subseqüente ls -lno mesmo arquivo mostra que o chownSUCESSO, embora chowntenha relatado falha e o subseqüente statconfirmou isso.

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

(Minha fakerootversão é 1.20.2 e meu sistema é Arch Linux com todas as atualizações.)

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

Responder1

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

Seu valor é significativo somente quando o valor de retorno da chamada indica um erro (ou seja, -1 na maioria das chamadas do sistema; -1 ou NULL na maioria das funções da biblioteca); uma função bem-sucedida pode alterar errno.

O valor in errnonão é significativo e chownde fato não falhou.

Conforme já discutido nos comentários, a stracesaída contém EPERM e uids/gids não falsificados conforme esperado, como stracerastreamentos abaixo da LD_PRELOADbiblioteca fakeroot. Imprimir o uid/gid do programa mostra a saída correta (falsificada).

informação relacionada