⬢ DragonFlyBSD Kernel Audit
DF-5722 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5722",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Resuming a DDB session that was entered from interrupt context (e.g. any breakpoint in clock/interrupt-path code such as b hardclock) deterministically panics the kernel with td_critcount is/would-go negative at the session-exit crit_exit() (db_interface.c:201 -> crit_exit_wrapper -> crit_panic, lwkt_thread.c:1772): one td_critcount decrement goes unmatched across the session. 3/3 boots on the stock snapshot kernel (UP guest); thread-context controls on the same kernel (sysctl-entry, single-step roundtrip, breakpoint hit in sys_kill resumed with c) are all clean, and the DF-5721 software watchpoint was exonerated by a no-watch bisect run. db_run.cs engine (the audited file) is context-agnostic and exonerated by identical captured state in surviving vs panicking runs; the defect lives in the machine layers crit accounting around kdb_trap for interrupt-context sessions. Root-console-only trigger (all unprivileged routes probed closed), so: Low severity, panic class \u2014 the practical cost is that debugging any interrupt-path code with DDB crashes the box.",
  "exploit_chain": "",
  "evidence": "run4-minimal-panic.serial.log (b hardclock / c / Breakpoint at hardclock / d hardclock / c / panic + crit_panic trace); run5-threadctx-control.serial.log (thread-context bp hit + c = alive); panic.watch.serial.log (run1 variant); README.md bisect matrix; three vmcores preserved in guest /var/crash",
  "kernel_refs": [
    "sys/platform/pc64/x86_64/db_interface.c:160",
    "sys/platform/pc64/x86_64/db_interface.c:201",
    "sys/kern/lwkt_thread.c:1766",
    "sys/kern/lwkt_thread.c:1772",
    "sys/platform/pc64/x86_64/ipl.s:281",
    "sys/platform/pc64/x86_64/ipl.s:304",
    "sys/ddb/db_run.c:199",
    "sys/ddb/db_run.c:164"
  ],
  "poc_changes": "No seed PoC. Built from scratch: UP/SMP socket-serial QEMU rigs, paced serial DDB driver, root-sysctl DDB entry, and the bisect battery across 6 boots (3 panic runs, 3 controls).",
  "attempts": 6,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0 Thu Jul 2 06:02:54 UTC 2026 x86_64",
  "runtime_sec": 1500,
  "guest_dirty": 0,
  "build_cmd": "(no compilation; DDB console session over serial socket)",
  "run_cmd": "./findings/poc/DF-5721/serial_vm1.sh up; ssh dfbsd sysctl debug.enter_debugger=ddb &; DF5721_SOCK=/tmp/opencode/df-5721up-ser.sock ./findings/poc/DF-5721/drive_ddb.py b hardclock 4 c 6 d hardclock 4 c 10",
  "code_hash": "d2ddfc831df07815aad62268d74dafffd091bac78ffa1e8ddcc391f1cdee803a",
  "notes": "Exact leak instruction not pinned (needs vmcore unwind; dumps preserved on guest /var/crash before reset). Fix ownership: db_interface.c/ipl.s, discovered during the sys/ddb/db_run.c pass-2 audit. Guest was reset with-src after evidence capture.",
  "recommended_fix": "kdb_trap: save curthread->td_critcount after crit_enter() and force-restore it at session exit instead of bare crit_exit() (see fix.diff); upstream-quality fix is to find the unmatched decrement in the interrupt-entry/polled-console path.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff authored post-verification against the read-only sys/ tree; not applied/rebuilt \u2014 the panic recipe needs a UP guest and a kernel rebuild on the 1-vCPU guest was not feasible in-run. Baseline (panic) reproduced 3/3.",
  "fix_evidence": "findings/poc/DF-5722/fix.diff"
}