DF-5322 / verdict.json
{ "finding_id": "DF-5322", "status": "reproduced", "reproduced": true, "impact": "leak", "confidence": "certain", "verdict": "Reproduced and measured on the QEMU guest with the production firewire.c compiled into a KLD harness: every split-transaction timeout leaks exactly one 16-byte struct tlabel because firewire_xfer_timeout() (firewire.c:348) unlinks the tlabel without kfree and the only free site, fw_tl_free() (firewire.c:900), requires list membership. 5000 timeouts -> M_FW inuse delta 5000 objects / 80000 bytes (baseline); 0/0 with fix.diff applied to /usr/src and the module rebuilt. Unbounded attacker-paced kernel memory exhaustion (DoS); no disclosure or corruption from this defect alone.", "exploit_chain": "open /dev/fwN.M (operator group) -> FW_ASYREQ to a non-answering node (or kernel fwmem traffic on a busy bus) -> each 200 ms split timeout leaks one M_FW tlabel -> unbounded slow kernel memory exhaustion.", "evidence": "run.log (baseline: M_FW inuse delta = 5000 objects, memuse delta = 80000 bytes ... LEAK REPRODUCED), fix_run.log (delta = 0 objects, memuse delta = 0 bytes), VERDICT.md", "kernel_refs": [ "sys/bus/firewire/firewire.c:320", "sys/bus/firewire/firewire.c:348", "sys/bus/firewire/firewire.c:890", "sys/bus/firewire/firewire.c:900", "sys/bus/firewire/firewire.c:994", "sys/bus/firewire/firewirereg.h:214" ], "poc_changes": "Harness is the DF-5321 module (df5322.c byte-identical to df5321.c; KMOD renamed df5322, sysctl names unchanged df5321_*); mode 0 measures the renamed M_FW malloc type in-kernel (ks_use[cpu].inuse/memuse summed) around the production timeout+free sequence with prewarmed zones.", "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": 12, "guest_dirty": 0, "build_cmd": "sh build.sh (cd /root/df5322 && make; compiles production /sys/bus/firewire/firewire.c into df5322.ko)", "run_cmd": "sh run.sh (sysctl kern.df5321_mode=0 kern.df5321_iters=5000; sysctl kern.df5321_fire=1)", "code_hash": "858fff8bd4cba49ad2c2a3d25388b80ca2b18eee26b30dc02c1ef27f16d7122d", "notes": "Baseline leak was first captured from the identical module artifact (df5321.ko, same source hash) during the DF-5321 run series, then re-confirmed from the DF-5322-named module after a fresh vm.sh reset with-src; fixed run on the patched source. Independent corroboration: DF-5321s baseline panics show the watchdog dereferencing tlabels freed by other paths (their lifetime is untracked after the timeout unlink).", "recommended_fix": "kfree(tl, M_FW) after STAILQ_REMOVE_HEAD in firewire_xfer_timeout() (carried inside the DF-5321 fix.diff serialization rework).", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Baseline: 5000 objects / 80000 bytes leaked over 5000 timeouts via the production path. Patched (fix.diff on /usr/src, module rebuilt, identical trigger): delta 0 objects / 0 bytes.", "fix_evidence": "fix_run.log, fix_build.log, fix.diff" } |