vop_compat_* '[diagnostic] EAGAIN on ncp %p %s' prints leak kernel namecache heap pointer and full pathname into the world-readable msgbuf
| Field | Value |
|---|---|
| ID | DF-2736 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N |
| CWE | CWE-532 Sensitive Information in Log |
| File | sys/kern/vfs_default.c |
| Lines | 200, 329, 408, 488, 567, 643, 726, 813, 883, 984, 1033 |
| Area | kern |
| Confidence | likely |
| Discovered | 2026-08-30 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | kernleak |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
Ten error paths in the VFS new-API-to-old-API compatibility fallbacks
(vop_compat_nresolve/ncreate/nmkdir/nmknod/nlink/nsymlink/nwhiteout/
nremove/nrmdir/nrename) print kprintf("[diagnostic]
vop_compat_resolve: EAGAIN on ncp %p %s\n", ncp, ncp->nc_name)
whenever vget(dvp, LK_EXCLUSIVE) fails β exactly when the directory
vnode is concurrently reclaimed, a race an unprivileged local user
widens by churning lookups/creates against vnode-cache pressure on hot
directories. The message discloses the exact kernel virtual address of
the struct namecache (namecache slab object) plus the entry name.
DragonFly's kernel message buffer is readable by any user by default
(security.unprivileged_read_msgbuf defaults to 1) β defeats
heap-address randomization and aids slab-grooming attacks chaining off
any other bug. Same class as DF-0920/DF-2614/DF-2637/DF-2689.
Recommended fix
Drop the %p (and ideally rate-limit or KTR the print) at all ten
sites:
kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %s\n",
ncp->nc_name);
Timeline
- 2026-08-30 Discovered during pass-2 audit of vfs_default.c (GLM 5.3).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2736 Β· 3 files| File | Type | Description | Size | |
|---|---|---|---|---|
| ncp_churn.c | β | 1.9 KB | view raw | |
| run.log | β | 241 B | view raw | |
| fix.diff | β | 3.2 KB | view raw |
Fix verification
not_testableAll ten %p/%s diagnostic prints stripped to a bare message; compile-validated. Print itself not triggered at runtime.
compile-validated in the fix-all kernel build (make nativekernel, 0 errors)
Confirmed kernel references
Detail
Evidence (decisive lines)
df2736_churn.log: 2.4M lookups, 0 prints; code at vfs_default.c:199-202; unpriv dmesg read works
PoC changes
none
Verified recommended fix
--- sys/kern/vfs_default.c 2026-06-29 12:51:19.000000000 +0000
Verdict
Code-certain but not triggered at runtime. All ten vop_compat_* fallbacks print [diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s with the namecache pointer and full pathname on vget(dvp, LK_EXCLUSIVE) failure (sys/kern/vfs_default.c:200 etc); the msgbuf is world-readable on this guest (security.unprivileged_read_msgbuf=1, verified by reading dmesg as an unprivileged user). UFS has no native nresolve so lookups on the /boot UFS mount exercise vop_compat_nresolve. Two churn runs as an unprivileged user (583K lookups; then 1.8M lookups with kern.maxvnodes lowered to 4000 to force vnode-cache pressure) produced zero EAGAIN-on-vget events: the blocking vget on a namecache-held directory vnode did not fail under this workload, so the print never fired. The disclosure path exists in code; triggering requires the concurrent-reclaim race to hit during a compat lookup, which this workload could not induce.
No comments yet.