%20EPERM%20%E3%82%92%E8%BF%94%E3%81%99%E3%81%AE%E3%81%AF%E3%81%AA%E3%81%9C%E3%81%A7%E3%81%99%E3%81%8B%3F.png)
使用中に奇妙な動作に遭遇しましたチョーン(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
ここで何が見えますか?
- 呼び出し
chown
は EPERM (操作が許可されていません) で失敗しました。 - 後続では、実際の(偽物ではない)UID と GID が
stat
表示されますst_uid=1001, st_gid=100
(fakeroot を正しく理解していれば、少なくとも が表示されるはずなので奇妙ですst_uid=0, st_gid=0
)。 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 を印刷すると、正しい (偽造された) 出力が表示されます。strace
LD_PRELOAD