Warum gibt chown innerhalb von Fakeroot EPERM zurück, obwohl es erfolgreich war (aber andererseits auch nicht)?

Warum gibt chown innerhalb von Fakeroot EPERM zurück, obwohl es erfolgreich war (aber andererseits auch nicht)?

Ich bin auf bizarres Verhalten gestoßen, wenn ichchown(2)innerhalb einer Fakeroot-Umgebung. Das folgende Minimalprogramm veranschaulicht das Problem:

#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;
}

Angenommen, das ist main.c. Jetzt führe ich Folgendes innerhalb eines aus 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

Was können wir hier sehen?

  1. Der chownAufruf ist mit EPERM (Operation Not Permitted) fehlgeschlagen.
  2. Nachfolgend statwird angezeigt st_uid=1001, st_gid=100, welche meine echte (nicht gefälschte) UID und GID ist (was komisch ist, denn wenn ich Fakeroot richtig verstehe, sollte zumindest angezeigt werden st_uid=0, st_gid=0).
  3. Das Nachfolgende ls -lin derselben Datei zeigt, dass der chownVorgang ERFOLGREICH war, obwohl chownein Fehler gemeldet wurde, und das Nachfolgende stathat dies bestätigt.

Was zum Teufel ist hier los? Habe ich einen Fehler in Fakeroot gefunden oder ist das nur ein Missverständnis darüber, wie Fakeroot funktioniert?

(Meine fakerootVersion ist 1.20.2 und mein System ist Arch Linux mit allen Updates.)

Aktualisieren:Jonas Wielicki hat richtig darauf hingewiesen, dass strace auf Systemaufrufebene arbeitet und daher irreführend ist, da die Ergebnisse der Systemaufrufe von libfakeroot verstümmelt werden, bevor sie an das Programm selbst zurückgegeben werden. Es stellt sich heraus, dass nach stat(path, &s)die struct stat sneue UID und GID enthalten ist. Aber es ist immer noch verwirrend, dass chownmit EPERM fehlschlägt.

Antwort1

chowngibt tatsächlich Null zurück, wenn es unter ausgeführt wird fakeroot. Somit gilt gemäß errno(3):

Sein Wert ist nur dann von Bedeutung, wenn der Rückgabewert des Aufrufs einen Fehler anzeigt (d. h. -1 bei den meisten Systemaufrufen; -1 oder NULL bei den meisten Bibliotheksfunktionen). Eine erfolgreiche Funktion darf errno ändern.

Der Wert in errnoist nicht signifikant und chownist tatsächlich nicht fehlgeschlagen.

Wie bereits in den Kommentaren erläutert, straceenthält die Ausgabe wie erwartet EPERM und nicht gefälschte UIDs/GIDs als straceSpuren unterhalb der Fakeroot- LD_PRELOADBibliothek. Das Drucken der UID/GID aus dem Programm zeigt die korrekte (gefälschte) Ausgabe.

verwandte Informationen