Non-root tmpfs mounts take attacker-supplied root uid/gid (only mode is sanitized): forged directory ownership plus statfs f_owner overwrite breaks the unmount-ownership authorization (mounter lockout / arbitrary-uid unmount grant)
Summary
tmpfs_mount copies ta_root_uid/ta_root_gid verbatim from the fully user-controlled tmpfs_mount_info (:142-144) and sanitizes only root_mode for non-root mounters (:151-155). Consequences: (a) a user-mounted tmpfs root directory reports arbitrary ownership (VERIFIED uid=0 gid=0 from uid 1001); (b) tmpfs_statfs overwrites f_owner with tm_root->tn_uid (:494), and sys_unmount authorizes by f_owner == cred->cr_uid || priv (vfs_syscalls.c:670) - VERIFIED: the real mounter's unmount now fails EPERM (self-lockout), symmetrically the forged uid is granted unmount/update rights on the attacker's mount. Unpriv user (vfs.usermount=1) forges audit-visible ownership of a live filesystem and manipulates who may unmount it; modest ceiling (no direct privilege gain) but defeats the kernel's mount-ownership model. Fix: root_uid/root_gid = cred's for non-root mounters + stop overwriting f_owner in statfs.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3183 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.6 KB | β raw | |
| VERDICT.md | β | 2.2 KB | β raw | |
| build.log | β | 65 B | view raw | |
| build.sh | β | 68 B | view raw | |
| env.txt | β | 419 B | view raw | |
| run.log | β | 1.1 KB | view raw | |
| run.sh | β | 91 B | view raw | |
| umount_demo.c | β | 3.3 KB | view raw | |
| verdict.json | β | 2.1 KB | view raw |
DF-3183 β non-root tmpfs mounts take attacker-supplied root uid/gid (mode is sanitized, ownership is not) β statfs f_owner forgery + unmount-permission confusion
What
tmpfs_mount (sys/vfs/tmpfs/tmpfs_vfsops.c:142-155) copies
ta_root_uid / ta_root_gid from the (fully user-controlled)
struct tmpfs_mount_info and only sanitizes root_mode for non-root
mounters:
root_uid = args.ta_root_uid; /* :142 β NOT sanitized below */
root_gid = args.ta_root_gid; /* :143 */
root_mode = args.ta_root_mode;
...
if (cred->cr_uid != 0) {
root_mode = VREAD; /* only mode is forced */
...
}
Consequences for a vfs.usermount=1 unprivileged mount:
* the tmpfs root directory is owned by any chosen uid/gid (e.g. 0);
* tmpfs_statfs overwrites f_owner with tm_root->tn_uid
(tmpfs_vfsops.c:494), and sys_unmount authorizes unmount by
mp->mnt_stat.f_owner == cred->cr_uid || priv
(sys/kern/vfs_syscalls.c:670) β so the forged uid can unmount the
attacker's mount, and the real mounter is locked out.
Observed (guest, user maxx uid 1001, vfs.usermount=1)
mounter uid=1001 euid=1001, spoofing ta_root_uid/gid=0, ta_size_max=1TiB statfs: f_blocks=268435456 ..., f_owner=0 (mounter is 1001) root dir owner: uid=0 gid=0 mode=40600 unmount by mounter: FAILED (Operation not permitted) β f_owner forged to 0
Control run without the spoof unmounts fine (unmount by mounter: OK).
Fix
For non-root mounters force root_uid = cred->cr_uid; root_gid =
cred->cr_gid; alongside the existing root_mode override, and stop
overwriting f_owner in tmpfs_statfs (leave the mounter's uid recorded
by the VFS layer).
DF-3183 verdict β REPRODUCED (non-root tmpfs mount forges root-dir uid/gid and statfs f_owner; unmount-permission confusion)
Guest: DragonFly 6.5-DEVELOPMENT #0 X86_64_GENERIC (INVARIANTS), vfs.usermount=1, unprivileged user maxx (uid 1001).
Observed (run.log):
mounter uid=1001 euid=1001, spoofing ta_root_uid/gid=0, ta_size_max=1TiB statfs: f_blocks=268435456 ..., f_owner=0 (mounter is 1001) root dir owner: uid=0 gid=0 mode=40600 unmount by mounter: FAILED (Operation not permitted) β f_owner forged to 0
Control (no spoof): f_owner=1001, root dir uid=1001, unmount OK.
Source: tmpfs_mount copies args.ta_root_uid/ta_root_gid verbatim (tmpfs_vfsops.c:142-144) and sanitizes only root_mode for non-root (:151-155). tmpfs_statfs then publishes tm_root->tn_uid as f_owner (:494), and sys_unmount authorizes by mp->mnt_stat.f_owner == cred->cr_uid || priv (kern/vfs_syscalls.c:670). Net effects: 1. forged f_owner β the named uid can unmount the attacker's mount (or mount -u update check at vfs_syscalls.c:263), while the real mounter is locked out (demonstrated: EPERM self-lockout); 2. the root directory of a user-mounted tmpfs reports arbitrary ownership (uid=0 gid=0 demonstrated) β auditing/ownership confusion (files created within still belong to the creating users).
Impact ceiling is modest (no direct privilege gain β permission checks on the spoofed-owned directory do not help the non-owner mounter; mode is forced to 0600). Filed Low: ownership/f_owner forgery on a usermountable filesystem plus unmount authorization confusion.
Status: reproduced / impact=none (privilege-relevant confusion only) / confidence certain.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
(No fix.diff for this item: documented recommendation only - see Fix above.)
Fix verification
not_testable[]
Confirmed kernel references
Detail
Evidence (decisive lines)
['run.log (spoof + control)', 'umount_demo.c', 'VERDICT.md']
PoC changes
same binary as DF-3182 (spoof uid argument)
Verified recommended fix
force root_uid/root_gid to cred values for non-root mounters; stop overwriting f_owner in tmpfs_statfs
Verdict
REPRODUCED (forgery): unprivileged mount (vfs.usermount=1) with ta_root_uid=0/ta_root_gid=0 produced a tmpfs whose root directory reports uid=0 gid=0 (mode correctly forced to 0600) and whose statfs f_owner is 0 while the mounter is uid 1001; the mounter's own unmount then fails EPERM (sys_unmount authorizes via mnt_stat.f_owner at vfs_syscalls.c:670, which tmpfs_statfs overwrote with tm_root->tn_uid at tmpfs_vfsops.c:494). Control run without spoof: f_owner=1001 and unmount OK. tmpfs_mount copies ta_root_uid/ta_root_gid verbatim (tmpfs_vfsops.c:142-144) and sanitizes only root_mode (:151-155). Impact ceiling modest: unmount-authorization confusion (forged uid may unmount/update the attacker's mount; real mounter locked out β demonstrated) and ownership spoofing; no direct privilege gain found.
No comments yet.