fakerootでchownが成功しても(成功しなくても)EPERMを返すのはなぜですか?

fakerootでchownが成功しても(成功しなくても)EPERMを返すのはなぜですか?

使用時に奇妙な動作が発生しました。村(2)fakeroot環境で。次の最小プログラムは問題を示しています。

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

yesと仮定main.cすると、次のコマンドを実行します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

ここで何を見ることができますか?

  1. chownEPERM(操作は許可されていません)のため、呼び出しは失敗します。
  2. それから私の実際の(偽ではない)UIDとGIDが何であるかをstat示しますst_uid=1001, st_gid=100(奇妙な理由は、私がfakerootを正しく理解している場合は少なくとも表示する必要があるためですst_uid=0, st_gid=0)。
  3. ls -l同じファイルの後続のコンテンツではレポートが失敗しましたが、後続のコンテンツではレポートが成功したことを確認chownしました。chownstat

正確に何が起こっているのでしょうか? fakerootでバグを見つけましたか、それともこれがfakerootのしくみについての誤解ですか?

(私のfakerootバージョンは1.20.2で、私のシステムはすべてのアップデートを含むArch Linuxです。)

修正する:Jonas Wielickiは、straceがシステムコールレベルで動作することを正しく指摘しました。これは、システムコールの結果がプログラム自体に返される前にlibfakerootによって破壊されるため、誤解を招く可能性があります。投稿に新しいUIDとGIDがstat(path, &s)含まれていることがわかりました。struct stat sしかし、chownEPERMの失敗は依然として謎のままです。

答え1

chown実際に以下で実行すると0が返されますfakeroot。したがって、次のようになりますerrno(3)

この値は、呼び出しの戻り値がエラー(つまり、ほとんどのシステム呼び出しの場合は-1、ほとんどのライブラリ関数の場合は-1、またはNULL)を表す場合にのみ意味があります。成功した関数はerrnoを変更することができます。

の価値はerrno重要ではなく、chown実際には失敗しません。

注釈ですでに説明したように、出力にはstracefakerootstraceリポジトリLD_PRELOADの下のトレースに示されているように、EPERMと予想される偽の非uids / gidが含まれます。プログラムでuid / gidを印刷すると、正しい(偽)出力が表示されます。

関連情報