I've been running into bizarre behavior when using chown(2) within a fakeroot environment.
The following minimal program illustrates the issue:
#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;
}
Suppose that is main.c
. Now I run the following within 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
What can we see here?
- The
chown
call failed with EPERM (Operation Not Permitted). - The subsequent
stat
showsst_uid=1001, st_gid=100
which is my real (non-fake) UID and GID (which is weird because, if I understand fakeroot correctly, it should at least showst_uid=0, st_gid=0
). - The subsequent
ls -l
on the same file shows that thechown
SUCCEEDED even thoughchown
reported failure and the subsequentstat
confirmed that.
What the heck is going on here? Have I found a bug in fakeroot, or is this just a misunderstanding of how fakeroot works?
(My fakeroot
is version 1.20.2, and my system is Arch Linux with all updates.)
Update: It has been correctly pointed out by Jonas Wielicki that strace works on the syscall level and thus is misleading since the results of the syscalls will be mangled by libfakeroot before being returned to the program itself. It turns out that after stat(path, &s)
, the struct stat s
contains the new UID and GID. But it's still confusing that chown
fails with EPERM.
Best Answer
chown
in fact returns zero when run underfakeroot
. Thus, according toerrno(3)
:The value in
errno
is not significant andchown
did in fact not fail.As already discussed in the comments, the
strace
output contains EPERM and non-faked uids/gids as expected, asstrace
traces below the fakerootLD_PRELOAD
library. Printing the uid/gid from the program shows the correct (faked) output.