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

が であると仮定します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. 呼び出しchownは EPERM (操作が許可されていません) で失敗しました。
  2. 後続では、実際の(偽物ではない)UID と GID がstat表示されますst_uid=1001, st_gid=100(fakeroot を正しく理解していれば、少なくとも が表示されるはずなので奇妙ですst_uid=0, st_gid=0)。
  3. ls -l同じファイルの次の行は、失敗が報告されたchownにもかかわらず SUCCEEDEDでありchown、次の行でstatそれが確認されたことを示しています。

一体何が起こっているのでしょうか? fakeroot のバグを見つけたのでしょうか、それともこれは単に fakeroot の動作に関する誤解なのでしょうか?

(私のfakerootバージョンは 1.20.2 で、私のシステムはすべてのアップデートが適用された Arch Linux です。)

アップデート:Jonas Wielicki 氏によって正しく指摘されているように、strace はシステム コール レベルで動作するため、システム コールの結果はプログラム自体に返される前に libfakeroot によって変更されるため、誤解を招く可能性があります。 の後stat(path, &s)、にはstruct stat s新しい UID と GID が含まれることがわかります。しかし、 が EPERM で失敗するのはまだ混乱を招きますchown

答え1

chown実際に で実行するとゼロを返しますfakeroot。したがって、 によればerrno(3)

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

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

コメントで既に説明したように、出力には、 fakeroot ライブラリの下のトレースstraceとして、予想どおり EPERM と偽造されていない uid/gid が含まれます。プログラムから uid/gid を印刷すると、正しい (偽造された) 出力が表示されます。straceLD_PRELOAD

関連情報