chmod -R changes entries below its command-line argument with a raw syscall(SYS_fchmodat2, ...) instead of a libc call, so LD_PRELOAD tools (fakeroot, fakechroot, pseudo) never see it. The mode changes on disk, but their bookkeeping does not, so later stat() calls report the old mode. Exit status is 0 and stderr is empty, so the loss is silent
This can be reproduced by running the following commands using uutils 0.10.0, fakeroot 1.37.1.2, Linux 6.16:
mkdir -p d/sub
fakeroot sh -c 'chown -R daemon:daemon d && chmod -R u+s d && find d -printf "%M %p\n" | sort'
GNU coreutils:
drwsrwxr-x d
drwsrwxr-x d/sub
uutils:
drwsrwxr-x d
drwxrwxr-x d/sub # setuid bit lost
The cause, as I have found, is that DirFd::chmod_at in src/uucore/src/lib/features/safe_traversal.rs calls libc::syscall(452, ...) directly. The command-line argument itself is unaffected because it goes through fs::set_permissions -> chmod()
The raw syscall is #[cfg]-gated to asm-generic arches (x86_64, x86, arm, aarch64, riscv), so it does not reproduce on e.g. ppc64el or s390x, which take the fchmodat fallback. Introduced by #11918
Same class as #13399, different call site (that one is rustix in id, this one is a hand-written libc::syscall in uucore)
chmod -Rchanges entries below its command-line argument with a rawsyscall(SYS_fchmodat2, ...)instead of a libc call, soLD_PRELOADtools (fakeroot, fakechroot, pseudo) never see it. The mode changes on disk, but their bookkeeping does not, so laterstat()calls report the old mode. Exit status is 0 and stderr is empty, so the loss is silentThis can be reproduced by running the following commands using uutils 0.10.0, fakeroot 1.37.1.2, Linux 6.16:
mkdir -p d/sub fakeroot sh -c 'chown -R daemon:daemon d && chmod -R u+s d && find d -printf "%M %p\n" | sort'GNU coreutils:
uutils:
drwsrwxr-x d drwxrwxr-x d/sub # setuid bit lostThe cause, as I have found, is that
DirFd::chmod_atinsrc/uucore/src/lib/features/safe_traversal.rscallslibc::syscall(452, ...)directly. The command-line argument itself is unaffected because it goes throughfs::set_permissions->chmod()The raw syscall is
#[cfg]-gated to asm-generic arches (x86_64,x86,arm,aarch64,riscv), so it does not reproduce on e.g. ppc64el or s390x, which take thefchmodatfallback. Introduced by #11918Same class as #13399, different call site (that one is rustix in
id, this one is a hand-writtenlibc::syscallin uucore)