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

devfs_allocv failure ignored: devfs_spec_open and devfs_vop_nlookupdotdot use the vp unconditionally β†’ vn_unlock(NULL)/NULL-fp panic under vnode exhaustion

Field Value
ID DF-3020
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H
CWE CWE-476
File sys/vfs/devfs/devfs_vnops.c
Lines 535-536, 933-978 (contrast :507)
Area vfs/devfs
Confidence speculative
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket memcorrupt
Reported pending
Known CVE none
CVE match novel

Summary

devfs_allocv can return an error leaving vpp=NULL. devfs_vop_nlookupdotdot:535-536 then vn_unlock(a_vpp) on NULL; in devfs_spec_open's clone path the (ignored) failure leaves vp=NULL, ap->a_vp=NULL, and :978 vn_unlock(vp=NULL) β€” kernel NULL-deref panic. Requires getnewvnode/vget failure β€” forceable via vnode-cache exhaustion pressure by an unprivileged user, otherwise rare; impact is a panic. Not executed (exhaustion setup time-heavy); code-path direct. Fix: check devfs_allocv's return (bail ENOENT in nlookupdotdot; treat clone allocv failure as failed clone in spec_open).

Timeline

  • 2026-09-02 Discovered during pass-2 audit of devfs_vnops.c (GLM 5.3).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3020 Β· 9 files
FileTypeDescriptionSize
README.md β€” 323 B ↓ raw
VERDICT.md β€” 1.3 KB ↓ raw
df3020.c β€” 853 B view raw
df3020b.c β€” 1.0 KB view raw
env.txt β€” 248 B view raw
fix.diff β€” 145 B view raw
manifest.json β€” 597 B view raw
run.log β€” 256 B view raw
verdict.json β€” 1.6 KB view raw

DF-3020 - devfs_allocv failure ignored -> vn_unlock(NULL) panic under vnode exhaustion

Severity Low | verdict: not_reproduced | impact: none

Reproduce

Sources in this directory; build with cc -O2 -o <bin> <src> -pthread on the guest.

See VERDICT.md for the full narrative and run.log for the decisive output.

VERDICT.md
↓ download raw

DF-3020 verification

Kernel: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64

Two attempts to force getnewvnode failure inside the ptmx clone path: (1) kern.maxvnodes=300 with 217,405 open/close cycles - zero failures, vnlru kept recycling; (2) kern.maxvnodes=120 while holding 1,001 ptmx fds open - further opens fail with ENODEV from the pty driver unit limit (bitmap exhausted near 1000 units), which fires inside the clone handler BEFORE devfs_allocv, so the ignored-error path is never reached. The NULL-deref code path is real (devfs_allocv can return error leaving *vpp NULL; devfs_vop_nlookupdotdot:535 and devfs_spec_open:933 ignore the return) but getnewvnode could not be made to fail from unprivileged pressure on this guest.

Kernel references

Fix

See fix.diff.

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.

Fix verification

not_testable
↓ fix.diffper-fix-DF-3020

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md + run.log + sources

PoC changes

adjusted from finding sketch to guest syscall/layout reality

Verified recommended fix

diff: check devfs_allocv return in devfs_vop_nlookupdotdot (bail ENOENT) and in devfs_spec_open clone path (treat as failed clone, vput orig).

Verdict

Two attempts to force getnewvnode failure inside the ptmx clone path: (1) kern.maxvnodes=300 with 217,405 open/close cycles - zero failures, vnlru kept recycling; (2) kern.maxvnodes=120 while holding 1,001 ptmx fds open - further opens fail with ENODEV from the pty driver unit limit (bitmap exhausted near 1000 units), which fires inside the clone handler BEFORE devfs_allocv, so the ignored-error path is never reached. The NULL-deref code path is real (devfs_allocv can return error leaving *vpp NULL; devfs_vop_nlookupdotdot:535 and devfs_spec_open:933 ignore the return) but getnewvnode could not be made to fail from unprivileged pressure on this guest.