DragonFlyBSD Kernel Audit
DF-3022 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3022",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "likely",
  "verdict": "Unprivileged pty-churn + /dev/pts stat race deadlocks the kernel: cache_resolve holds the parent ncp lock across VOP_NRESOLVE while devfs_vop_nresolve takes devfs_lock (vnops.c:474), and the devfs core destroy path holds devfs_lock across devfs_unlinkp's cache_inval_vp -> cache_zap on the same ncp (devfs_core.c:626-627). Observed as a full system wedge (~6 min into the racer on the DF-3017-patched kernel #1, where the competing sysref panic no longer masks it): spin_lock_ex 'cache_zap, indefinite wait', then [diagnostic] cache_lock_shared blocks for df3017 and finally sshd-session on /dev/urandom, guest unreachable. On the stock kernel the same interleaving overwhelmingly manifests as DF-3017's panic instead, which is why this second bug was invisible before. Pure deadlock DoS, no corruption.",
  "exploit_chain": "open/close /dev/ptmx churn (destroy thread: devfs_lock EX -> cache_inval_vp -> cache_zap spins on ncp of /dev/pts/N) || concurrent lstat(/dev/pts/N) (lookup thread: ncp EX held by cache_resolve -> VOP_NRESOLVE -> devfs_lock EX blocked) -> circular wait -> every /dev path resolution system-wide blocks -> sshd/shells hang -> guest dead",
  "evidence": [
    "findings/poc/DF-3022/wedge-console.txt - spin_lock_ex cache_zap indefinite wait + cache_lock_shared cascade + sshd-session blocked on /dev/urandom, guest wedged",
    "sys/kern/vfs_cache.c:4404-4418 - ncp held locked across VOP_NRESOLVE",
    "sys/vfs/devfs/devfs_core.c:626-627 - cache_inval_vp under devfs_lock"
  ],
  "kernel_refs": [
    "sys/vfs/devfs/devfs_vnops.c:474",
    "sys/vfs/devfs/devfs_core.c:626-627",
    "sys/kern/vfs_cache.c:4404-4418",
    "sys/kern/vfs_cache.c:2884"
  ],
  "poc_changes": "No separate PoC; the DF-3017 racer (findings/poc/DF-3017/df3017.c) triggers this once DF-3017's panic is out of the way.",
  "attempts": 1,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Sat Sep  5 10:33:01 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (fix.diff v2 applied)",
  "runtime_sec": 420,
  "guest_dirty": 0,
  "build_cmd": "(same racer as DF-3017) cc -O2 -pthread -o df3017 df3017.c",
  "run_cmd": "./df3017 480  (as nobody; wedge at ~6min)",
  "code_hash": "9f331aecf3d52379cccf60ace77e88a2489172030c1c29285010532cea3006bf",
  "notes": "Not fixed in this run: the correct fix is protocol-level (do not acquire ncp locks under devfs_lock in the destroy path, or retry in nresolve) and overlaps the fresh devfs_core pass-2 findings; flagged for upstream. Stock kernels hit DF-3017's panic first in this racer's timing profile, so a stock-only demonstration of the wedge would need DF-3017 separately fixed or a tweaked racer.",
  "recommended_fix": "Perform cache_inval_vp() outside devfs_lock in devfs_unlinkp() (node->v_node keeps the vp referenced across the window), or make devfs_vop_nresolve() release/retry when the destroy side holds devfs_lock; requires upstream analysis vs devfs_core serialization."
}