web-dev-qa-db-ja.com

fakeroot内で、chownが成功したにもかかわらず(しかし、再び成功しなかった)、なぜEPERMを返すのですか?

偽のルート環境で chown(2) を使用すると、奇妙な動作が発生します。次の最小限のプログラムは、問題を示しています。

_#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. 後続のstatは_st_uid=1001, st_gid=100_を表示します。これは私の実際の(偽ではない)UIDとGIDです(fakerootを正しく理解していれば、少なくとも_st_uid=0, st_gid=0_を表示するはずなので奇妙です)。
  3. 同じファイルの後続の_ls -l_は、chownが失敗を報告し、後続のchownがそれを確認したにもかかわらず、statが成功したことを示しています。

ここで一体何が起こっているのですか? fakerootにバグを見つけましたか、それともfakerootがどのように機能するかについての誤解ですか?

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

更新:straceはsyscallレベルで機能し、syscallの結果が次のように混乱するため、誤解を招く可能性があることがJonasWielickiによって正しく指摘されています。プログラム自体に返される前のlibfakeroot。 stat(path, &s)の後、_struct stat s_には新しいUIDとGIDが含まれていることがわかります。しかし、chownがEPERMで失敗することはまだ混乱しています。

3
Stefan Majewsky

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

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

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

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

5
Jonas Schäfer