⬢ DragonFlyBSD Kernel Audit
DF-5415 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5415",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Reproduced on the QEMU guest by calling the production fw_kqfilter with d->ir == NULL (the state after open(2) before any FW_SRSTREAM): fwdev.c:739-740 builds klist = &ir->rkq.ki_note at NULL+0x98 and knote_insert() dereferences it, panicking the kernel (assertion kn->kn_status & KN_PROCESSING failed in knote_insert, trace pins fw_kqfilter+0x8e). The guest went down (ssh dead, vm.sh status down). Local DoS for any user able to open /dev/fwN.M (0660 root:operator). The same hole exists for EVFILT_WRITE when only the transmit stream is configured, because fwdev.c:731-732 hooks ir instead of it. Fix validated: NULL check returns ENODEV (fw_kqfilter returned 19), no panic, guest alive.",
  "exploit_chain": "open /dev/fw0.0 (operator) -> kqueue() -> kevent(EVFILT_READ, EV_ADD) -> fw_kqfilter with d->ir==NULL -> knote_insert writes/reads at NULL+offsetof(fw_xferq,rkq)=0x98 -> kernel panic (reliable local DoS)",
  "evidence": "panic.txt (panic signature + trace with fw_kqfilter+0x8e), fix_run.log (df5415: ... returned 19 on the patched module, guest alive), fix.diff, build.log, fix_build.log",
  "kernel_refs": [
    "sys/bus/firewire/fwdev.c:721",
    "sys/bus/firewire/fwdev.c:730",
    "sys/bus/firewire/fwdev.c:732",
    "sys/bus/firewire/fwdev.c:739",
    "sys/bus/firewire/fwdev.c:740"
  ],
  "poc_changes": "Same shared harness (df5413.c test 5): fake cdev with fw_drv1{ir=NULL} and a real knote (EVFILT_READ); production fw_kqfilter does the rest.",
  "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": 1380,
  "guest_dirty": 0,
  "build_cmd": "sh build.sh  (cd /root/df5413 && make; compiles production firewire.c+fwdma.c+fwdev.c into df5413.ko)",
  "run_cmd": "sh run.sh  (kldload df5413.ko; sysctl kern.df5413_test=5; expect panic, capture serial console)",
  "code_hash": "528bb42b35a2e37de5d5e534e5a6eebd9ac13c30ec32c5b5f9313ca96624931a",
  "notes": "Hardware-gated only for the /dev/fw node (no OHCI in QEMU); the production kqfilter code itself executed and panicked. The panic manifests as a knote_insert assertion on the NULL-derived address rather than a bare page fault - equally fatal, trace pins fw_kqfilter.",
  "recommended_fix": "fw_kqfilter: if (ir == NULL) { ap->a_result = ENODEV; return 0; } (and hook EVFILT_WRITE to d->it as modern FreeBSD does) - as in fix.diff.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "Baseline: kernel panic in fw_kqfilter (guest down). Patched (fix.diff on /usr/src, module rebuilt, same trigger): fw_kqfilter returns 19 (ENODEV), no panic, guest alive through the rest of the battery.",
  "fix_evidence": "fix_run.log (df5415: ... returned 19), fix_build.log, fix.diff"
}