我在使用时遇到了奇怪的行为庄(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 显示正确的(伪造的)输出。