# DF-2524 VERDICT — REPRODUCED (production handler, stock module; kernel panic)

**Status: reproduced (panic)** — the production `trm_Disconnect()`
(sys/dev/disk/trm/trm.c:2354-2356) fetches `pSRB = pDCB->pActiveSRB` and
immediately dereferences `pSRB->pccb` with **no NULL guard** (the
author's own comment at :2355: `/* bug pSRB=0 */`). Dispatching the
running kernel's own `trm_Interrupt()` with `INT_DISCONNECT` while
`pACB->pActiveDCB != NULL` and that DCB's `pActiveSRB == NULL` produced
an immediate kernel panic: `Fatal trap 12`, fault address 0x58 — exactly
`offsetof(struct _SRB, pccb)`. The guard fix returns cleanly on a
rebuilt module.

## Rig (production code)

Same production-handler rig as DF-2522/23: real `/boot/kernel/trm.ko`
loaded (`trm_Disconnect` is inlined into `trm_Interrupt`), fabricated
ACB/DCB, register file emulated behind the kernel's own `bus_space`
accessors, dispatch of the module's real `trm_Interrupt()`
(0xffffffff826001d40). The chip choreography: `SCSI_STATUS` has
`SCSIINTERRUPT`, `SCSI_INTSTATUS = INT_DISCONNECT` — the same branch a
selection timeout takes (trm.c:1323-1325).

## What the run showed (stock module, panic.txt / run.log)

```
df2524: offsetof(SRB,pccb)=88 -> faulting read at 0x58
df2524: dispatching production trm_Interrupt: DISCONNECT with
        pACB->pActiveDCB=0xfffff8008d9e4560, pDCB->pActiveSRB=NULL
Fatal user address access from kernel mode from sysctl at ffffffff82601ea6
Fatal trap 12: page fault while in kernel mode
cpuid = 0; lapic id = 0
fault virtual address	= 0x58
fault code		= supervisor read data, page not present
instruction pointer	= 0x8:0xffffffff82601ea6      (= trm.ko + 0x1ea6)
stack pointer	        = 0x10:0xfffff801182f56f8
current process		= 854 (the sysctl dispatch thread)
kernel: type 12 trap, code=0
Stopped at      trm_Interrupt+0x166:    movq    0x58(%r12),%rax
db>
```

`0x58 = 88 = offsetof(struct _SRB, pccb)` (trm.h:160): the faulting
instruction is precisely the `pSRB->pccb` load of
`target_id = pSRB->pccb->ccb_h.target_id` (trm.c:2356) with
`pSRB == NULL` in `%r12`. Kernel trapped into ddb — unrecoverable
panic. Full serial capture in `panic.txt`.

## When the state occurs on hardware

`pActiveDCB` and the DCB's `pActiveSRB` are set together by
`trm_StartSCSI` (trm.c:1286-1287), but they are **not** cleared
together everywhere: `trm_Disconnect` itself clears `pDCB->pActiveSRB`
at trm.c:2402 (SRB completion) *after* `pACB->pActiveDCB` survives
other paths — e.g. `trm_ScsiRstDetect` only clears `pActiveDCB` in its
RESET_DETECT branch (trm.c:2805), and the bus-reset/recovery/abort
machinery (`trm_RecoverSRB`, `trm_DoingSRB_Done`) requeues and clears
SRB lists while a device keeps asserting disconnect/selection-timeout
interrupts. A misbehaving SCSI target can drive DISCONNECT/
SELTIMEOUT interrupts at any time (both take the same branch,
trm.c:1323); whenever one lands in the window where the DCB is still
the active DCB but its `pActiveSRB` has been cleared, the driver
panics. The author flagged exactly this with `/* bug pSRB=0 */`. The
rig fabricates that acknowledged state directly and shows the
unguarded deref is a kernel panic — the missing-guard defect itself,
not a new state-machine claim.

## Fix validation (fix.diff, run.patched.log, fix_build.log)

The fix adds the missing guard: a disconnect with no active SRB now
recovers the bus (`DO_CLRFIFO | DO_HWRESELECT`, the same recovery the
`pDCB == NULL` exception branch uses at trm.c:2349-2352) and returns.
(It deliberately omits that branch's `crit_exit()` — see incidental
note below.) On the rebuilt module (same `fix.all.diff` build as
DF-2522/23; this scenario touches only the Disconnect hunk):

```
df2524: dispatching production trm_Interrupt: DISCONNECT with
        pACB->pActiveDCB=0xfffff8008faabc70, pDCB->pActiveSRB=NULL
df2524: trm_Interrupt RETURNED - no NULL deref (guard present)
```

Guest stayed up; no trap. Baseline (panic) vs patched (clean return)
is the decisive pair.

## Incidental observation (not part of this finding)

The adjacent exception branch at trm.c:2343-2352 (`pDCB == NULL`) ends
with a `crit_exit()` that has **no matching `crit_enter()`** anywhere in
`trm_Disconnect` — an unbalanced crit-section exit (critcount
underflow) on that path. My fix's guard does not replicate it. Worth a
separate look.

## Bottom line

Real bug, acknowledged in-source, reproduced as a hard kernel panic
through the running kernel's own driver code at the exact cited
instruction; one-guard fix eliminates it, verified on a rebuilt module.
Gate: machines with Tekram DC395/TRM-S1040 HBAs and a misbehaving
device (or racing recovery) producing the no-active-SRB disconnect.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
