DF-2524 / verdict.json
{ "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." } |