
我在使用時遇到了奇怪的行為莊(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
.現在我在 a 中執行以下命令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(不允許操作)。 - 隨後
stat
顯示st_uid=1001, st_gid=100
哪一個是我真實的(非假的)UID 和 GID(這很奇怪,因為如果我正確理解 fakeroot,它至少應該顯示st_uid=0, st_gid=0
)。 ls -l
同一文件的後續內容顯示,chown
儘管chown
報告失敗,但後續內容stat
已確認,但仍成功。
這到底是怎麼回事?我是否發現了 fakeroot 中的錯誤,或者這只是對 fakeroot 工作原理的誤解?
(我的fakeroot
版本是1.20.2,我的系統是帶有所有更新的Arch Linux。)
更新:Jonas Wielicki 正確地指出 strace 在系統呼叫層級運作,因此具有誤導性,因為系統呼叫的結果在返回程式本身之前會被 libfakeroot 破壞。事實證明,在 之後stat(path, &s)
,struct stat s
包含新的 UID 和 GID。但chown
EPERM 失敗仍然令人困惑。
答案1
chown
事實上,在 下運行時返回零fakeroot
。因此,根據errno(3)
:
只有當呼叫的返回值指示錯誤時,其值才有意義(即,大多數系統呼叫為 -1;大多數函式庫函數為 -1 或 NULL);成功的函數可以更改 errno。
的價值errno
並不重要,而且chown
事實上並沒有失敗。
正如評論中已經討論的那樣,strace
輸出包含 EPERM 和預期的非偽造 uids/gids,如strace
fakerootLD_PRELOAD
庫下面的追蹤一樣。從程式列印 uid/gid 顯示正確的(偽造的)輸出。