Dentro de fakeroot, ¿por qué chown devuelve EPERM a pesar de que tiene éxito (pero tampoco lo hizo)?

Dentro de fakeroot, ¿por qué chown devuelve EPERM a pesar de que tiene éxito (pero tampoco lo hizo)?

Me he encontrado con un comportamiento extraño al usarchow(2)dentro de un entorno fakeroot. El siguiente programa mínimo ilustra el 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;
}

Supongamos que eso es main.c. Ahora ejecuto lo siguiente dentro de un 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

¿Qué podemos ver aquí?

  1. La chownllamada falló con EPERM (Operación no permitida).
  2. Lo siguiente statmuestra st_uid=1001, st_gid=100cuál es mi UID y GID real (no falso) (lo cual es extraño porque, si entiendo fakeroot correctamente, al menos debería mostrarse st_uid=0, st_gid=0).
  3. Lo siguiente ls -len el mismo archivo muestra que TUVO chownÉXITO a pesar de que chownse informó una falla y lo siguiente statlo confirmó.

¿Qué diablos está pasando aquí? ¿He encontrado un error en fakeroot o se trata simplemente de un malentendido sobre cómo funciona fakeroot?

(La mía fakerootes la versión 1.20.2 y mi sistema es Arch Linux con todas las actualizaciones).

Actualizar:Jonas Wielicki ha señalado correctamente que strace funciona en el nivel de llamada al sistema y, por lo tanto, es engañoso ya que libfakeroot alterará los resultados de las llamadas al sistema antes de devolverlos al programa mismo. Resulta que después de stat(path, &s), struct stat scontiene el nuevo UID y GID. Pero sigue siendo confuso que chownfalle con EPERM.

Respuesta1

chownde hecho, devuelve cero cuando se ejecuta bajo fakeroot. Así, según errno(3):

Su valor es significativo sólo cuando el valor de retorno de la llamada indicó un error (es decir, -1 en la mayoría de las llamadas al sistema; -1 o NULL en la mayoría de las funciones de biblioteca); una función que tiene éxito puede cambiar el error.

El valor en errnono es significativo y chownde hecho no falló.

Como ya se analizó en los comentarios, la stracesalida contiene EPERM y uids/gids no falsificados como se esperaba, como stracerastros debajo de la LD_PRELOADbiblioteca fakeroot. La impresión del uid/gid del programa muestra la salida correcta (falsa).

información relacionada