β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2736

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.

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2736 Β· 3 files
FileTypeDescriptionSize
ncp_churn.c β€” 1.9 KB view raw
run.log β€” 241 B view raw
fix.diff β€” 3.2 KB view raw

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

All 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)
↓ fix.diffper-fix-DF-2736

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.