DragonFlyBSD Kernel Audit
DF-2942 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2942",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "none",
  "confidence": "likely",
  "verdict": "Mechanism reproduced on the stock INVARIANTS guest via a KLD probe with a synthetic sysref_class. sysref_activate()'s only gate, the KASSERT at kern_sysref.c:280, accepts count == -0x40000000 -- the exact termination-in-progress state entered by _sysref_put's 1 -> -0x40000000 cmpset (:323). Calling sysref_activate() on a terminating object resurrected it to refcnt +1 with zero layer diagnostics on the INVARIANTS kernel, and the protocol then invoked the class terminate callback a SECOND time (run.log: term_count=2, 'CONFIRMED DOUBLE TERMINATION'); a probe variant re-activating on every termination produced 292 consecutive re-terminations ending in a fatal double fault from kernel stack exhaustion (run.1.unbounded.log). For a real class a double terminate re-runs the teardown (cdev's devfs_cdev_terminate would double devfs_release_ops and double-unlock devfs_lock), and the unbounded variant is a guaranteed stack-exhaustion panic. Attacker reachability: none in-tree -- the only live sysref_activate caller is devfs_new_cdev (devfs_core.c:2443), invoked exactly once right after sysref_alloc; the finding is the layer's ambiguous negative space (latent hardening gap, no SRF_TERMINATING distinction).",
  "exploit_chain": "",
  "evidence": "findings/poc/DF-2942/run.log: 'DF-2942: after activate refcnt=1 (RESURRECTED; kern_sysref.c:280 KASSERT passed, no diagnostic)' followed by terminate#2 and 'A: CONFIRMED DOUBLE TERMINATION (terminate callback ran twice for one object)'.\nfindings/poc/DF-2942/run.1.unbounded.log: 292 consecutive terminate re-entries then 'Fatal double fault' / 'panic: double fault' (stack exhaustion via sysref_put -> _sysref_put -> ops.terminate recursion).\nfindings/poc/DF-2942/build.log: clean KLD build (cc 8.3, INVARIANTS kernel #0).\nsys/kern/kern_sysref.c:280-281 accepting KASSERT; :164 init sentinel; :323 termination transition; sys/sys/sysref.h:115-117 flag bits (no TERMINATING).",
  "kernel_refs": [
    "sys/kern/kern_sysref.c:278",
    "sys/kern/kern_sysref.c:280",
    "sys/kern/kern_sysref.c:164",
    "sys/kern/kern_sysref.c:323",
    "sys/sys/sysref.h:115",
    "sys/vfs/devfs/devfs_core.c:2443",
    "sys/vfs/devfs/devfs_core.c:2487"
  ],
  "poc_changes": "Authored from scratch (no seed): synthetic sysref_class KLD mirroring devfs_cdev_terminate's lock/unlock/terminate protocol; the activate-during-termination call is made from inside the terminate callback (deterministic simulation of a racing misuser) with a one-shot flag; run 1 accidentally demonstrated the unbounded variant before the flag was added (kept as run.1.unbounded.log).",
  "attempts": 2,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 420,
  "guest_dirty": 0,
  "build_cmd": "ssh -F dfbsd-qemu/config dfbsd 'cd /root/sysref_probe && make'  (after scp of sysref_probe.c + Makefile)",
  "run_cmd": "ssh -F dfbsd-qemu/config dfbsd 'kldload /root/sysref_probe/sysref_probe.ko'",
  "code_hash": "8e3ef23300267dbc68db2f94e6e462d035b87f6a8c76f1343ae27194d0ea81a7",
  "notes": "Guest reset (with-src) after the run; guest_dirty=0. Same probe module/run as DF-2941 (shared evidence). In-tree single-caller discipline verified by rg: sysref_activate appears only at devfs_core.c:2443.",
  "recommended_fix": "Add an SRF_TERMINATING flag set on the 1 -> -0x40000000 transition and cleared on (re)initialization, and extend sysref_activate's KASSERT to reject terminating objects so the initializing and terminating negative-space states are no longer ambiguous.",
  "fix_status": "not_testable",
  "fix_verdict": "Fix authored post-verification (fix.diff); not build-validated: Info hardening finding, the fix's observable effect is the new assert path itself; no corruption was reproduced to A/B test against."
}