在 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.现在我在 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

我们在这里能看到什么?

  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。)

更新:Jonas Wielicki 正确地指出 strace 在系统调用级别工作,因此具有误导性,因为系统调用的结果在返回到程序本身之前会被 libfakeroot 破坏。事实证明,在 后stat(path, &s)struct stat s包含新的 UID 和 GID。但chownEPERM 失败仍然令人困惑。

答案1

chown事实上,在 下运行时返回零fakeroot。因此,根据errno(3)

仅当调用的返回值指示错误时,其值才有意义(即,大多数系统调用为 -1;大多数库函数为 -1 或 NULL);成功的函数可以更改 errno。

的价值errno并不重要,而且chown事实上并没有失败。

正如评论中已经讨论的那样,strace输出包含 EPERM 和预期的非伪造 uids/gids,如stracefakerootLD_PRELOAD库下面的跟踪一样。从程序打印 uid/gid 显示正确的(伪造的)输出。

相关内容