⬢ DragonFlyBSD Kernel Audit
DF-2524 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2524",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Reproduced with the production handler: dispatched the real trm_Interrupt() of kldloadd /boot/kernel/trm.ko with INT_DISCONNECT while pACB->pActiveDCB points at a DCB whose pActiveSRB is NULL. Production trm_Disconnect (trm.c:2354-2356, the authors own in-source comment at :2355 reads bug pSRB=0) immediately executes target_id = pSRB->pccb->ccb_h.target_id with pSRB==NULL: Fatal trap 12, fault virtual address 0x58 = offsetof(struct _SRB, pccb) (trm.h:160), instruction pointer trm_Interrupt+0x166 (module base 0xffffffff82600000 + 0x1ea6), Stopped at trm_Interrupt+0x166: movq 0x58(%r12),%rax - the exact cited dereference. Kernel trapped into ddb; serial capture in panic.txt. The state is the one the author acknowledged: pActiveDCB and pActiveSRB are set together by trm_StartSCSI (trm.c:1286-1287) but not cleared together (trm.c:2402 clears pActiveSRB while reset/abort recovery paths handle pActiveDCB separately), and a misbehaving device can assert DISCONNECT/SELTIMEOUT (same branch, trm.c:1323) at any time. The NULL-guard fix returns cleanly on a rebuilt module.",
  "exploit_chain": "NULL-deref kernel panic (read at 0x58); no info-leak or control-flow primitive - impact is denial of service (crash).",
  "evidence": "panic.txt / run.log: Fatal trap 12: page fault while in kernel mode ... fault virtual address = 0x58 ... Stopped at trm_Interrupt+0x166: movq 0x58(%r12),%rax; rig pre-printed offsetof(SRB,pccb)=88 -> faulting read at 0x58; run.patched.log: df2524: trm_Interrupt RETURNED - no NULL deref (guard present), guest up.",
  "kernel_refs": [
    "sys/dev/disk/trm/trm.c:2354",
    "sys/dev/disk/trm/trm.c:2355",
    "sys/dev/disk/trm/trm.c:2356",
    "sys/dev/disk/trm/trm.c:1323",
    "sys/dev/disk/trm/trm.c:1286",
    "sys/dev/disk/trm/trm.c:2402",
    "sys/dev/disk/trm/trm.h:160"
  ],
  "poc_changes": "No seed PoC existed (empty pack). Built from scratch: production-handler dispatch rig (kldload real trm.ko; trm_Disconnect reached via the modules inlined trm_Interrupt at kldstat base + nm offset 0x1d40); INT_DISCONNECT choreography through register-file emulation behind the kernels own bus_space accessors.",
  "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": 700,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df252x && make -m /usr/src/share/mk   (kldload trm; kldload ./df252x_trm_rig.ko)",
  "run_cmd": "sh run.sh   (sysctl kern.df252x.addr=<base+0x1d40>; sysctl kern.df252x.go=3 -> Fatal trap 12; capture: vm.sh log 40)",
  "code_hash": "75af3495eff0b1836d378d698019b7fd7e88c49a36b8c267c8f8ac3cfe6faa70",
  "notes": "Fix validated on a module carrying all three trm fixes (fix.all.diff in the shared build); this scenario dispatches exclusively through the Disconnect hunk. Incidental observation filed in VERDICT.md: the adjacent pDCB==NULL branch at trm.c:2343-2352 ends with an unbalanced crit_exit() (no matching crit_enter in trm_Disconnect) - the fix deliberately does not replicate it; worth a separate finding.",
  "recommended_fix": "Guard the fetch: if (pSRB == NULL) recover the bus (DO_CLRFIFO|DO_HWRESELECT write) and return instead of dereferencing pSRB->pccb.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Rebuilt the driver module from the patched source (same nativekernel build as DF-2522, full log fix_build.log) and re-ran the identical scenario against the patched modules own trm_Interrupt: df2524: trm_Interrupt RETURNED - no NULL deref (guard present), guest stayed up, no trap. Baseline panic gone.",
  "fix_evidence": "run.patched.log: df2524: trm_Interrupt RETURNED - no NULL deref (guard present) vs panic.txt: Fatal trap 12 ... fault virtual address = 0x58 ... Stopped at trm_Interrupt+0x166: movq 0x58(%r12),%rax."
}