# DF-2523 VERDICT — REPRODUCED (production handler, stock module; guest wedged)

**Status: reproduced (DoS)** — the production `trm_Reselect()` DCB ring
walk (sys/dev/disk/trm/trm.c:2428-2431) has **no exit** when the
reselecting target/LUN matches no DCB. Dispatching the running kernel's
own `trm_Interrupt()` with `INT_RESELECTED` and an unmatchable
`RselTarLunId` never returned: heartbeat callouts confirmed the thread
inside the loop at 3 s, 6 s and 9 s, and the guest subsequently wedged
completely (ssh dead, serial console dead, no panic printed; recovery
required killing QEMU). The bounded-walk fix returns immediately on a
rebuilt module.

## Rig (production code)

Same production-handler rig as DF-2522/24: real `/boot/kernel/trm.ko`
loaded, fabricated post-attach ACB with a circular 3-DCB ring
(ID/LUN = 1/0, 2/0, 3/2 — `DeviceCnt=3`, production ring bookkeeping),
TRM-S1040 register file emulated behind the kernel's own `bus_space`
accessors, dispatch of the module's real `trm_Interrupt()`
(0xffffffff826001d40).

* **Control (`go=4`)**: `TRMREG_SCSI_TARGETID = 0x0203` packs exactly as
  `*(u_int16_t*)&DCB->TargetID` for ring[2] (TargetID=3, LUN=2 — the
  comparison at trm.c:2428 reads TargetID | LUN<<8). Production
  `trm_Reselect` found it, armed the unexpected-reselection abort
  (`pActiveDCB=ring[2]`, `pActiveSRB=&TmpSRB`,
  `TmpSRB.SRBState=SRB_UNEXPECT_RESEL`, `MSG_ABORT` in `MsgOutBuf`,
  `DO_DATALATCH` written) and **returned** — behavioral proof the
  production code executed.
* **DF-2523 (`go=5`)**: `TRMREG_SCSI_TARGETID = 0x1000`. The driver
  masks the register with 0x1FFF (trm.c:2426) but a DCB can only pack
  to `(LUN<<8)|ID ≤ 0x070F` (16 targets, 8 LUNs), so bits 11-12 are
  **unmatchable by construction** — a reselection driven by a
  malicious or glitching SCSI device (the chip's hardware reselect is
  enabled, `DO_HWRESELECT`) enters a loop with no exit: the list is
  circular, there is no iteration bound, no counter, no NULL/identity
  exit (trm.c:2428-2431).

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

Dispatch ran in a dedicated kernel thread (`df2523_t1`) with 3 s
heartbeat callouts:

```
df2523[T1]: entering production trm_Interrupt (RESELECTED,
            RselTarLunId=0x1000 matches NO DCB of the 3-DCB circular list)
df2523[HB]: *** NON-TERMINATION CONFIRMED: 3.-08038 s inside
            trm_Interrupt/trm_Reselect ***   (×3: 3 s, 6 s, 9 s)
```

The `RETURNED` marker never printed. Within roughly a minute the whole
guest wedged: further ssh commands produced "Connection timed out during
banner exchange", `vm.sh status` went `down`, and shutdown reported
"guest not answering (likely DDB on panic); killing qemu" — an
**unkillable kernel thread spinning in production driver code starved
DragonFly's per-CPU user scheduler** until userland (sshd, getty, the
serial console) stopped responding. No kernel panic was printed — the
machine was simply dead.

On real hardware the same loop runs in the driver's interrupt handler
(registered via `bus_setup_intr`, trm_attach), i.e. at interrupt/crit
priority: the loop hard-locks the CPU (clock interrupts included) the
moment it is entered — strictly worse than the rig's thread-context
demonstration. The only recovery is the SCSI bus reset that can never
happen because the CPU that would issue it is the one spinning.

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

The fix bounds the walk by the driver's own ring bookkeeping
(`pACB->DeviceCnt`) and, when the reselection matches no DCB, drops the
connection (`STOPDMAXFER` + `DO_CLRFIFO|DO_HWRESELECT` — the recovery
the driver's `pDCB==NULL` exception branch already uses) and returns.
It deliberately does NOT loop on `DO_RSTSCSI` (that would add a second
unbounded register poll). Validated on the rebuilt module (same
`fix.all.diff` kernel/module build as DF-2522/24; this scenario touches
only the reselect hunk):

```
df2523[T1]: entering production trm_Interrupt (RESELECTED,
            RselTarLunId=0x1000 matches NO DCB of the 3-DCB circular list)
df2523[T1]: trm_Interrupt RETURNED (unreachable on vulnerable kernel)
```

No heartbeat fired, `uptime` answered, guest stayed healthy; the
matching control (`go=4`) behaved identically to stock
(pActiveDCB=ring[2], TmpSRB abort path).

## Things checked and killed

* "The chip would never deliver such a value": the register is 13 bits
  and the driver masks 0x1FFF while DCB encodings cap at 0x070F — any
  stray high bit (device-controlled reselection bytes) yields an
  unmatchable value. Premise stands.
* My rig's spin could be a rig artifact: ruled out by the control
  dispatch returning through the identical production path with only
  the register value different (match vs no-match is the sole
  differential).
* Wedge attribution: heartbeat non-termination precedes the wedge;
  nothing else runs in T1. The wedge is the OS-level consequence of the
  non-terminating production loop.

## Bottom line

Real bug, demonstrated through the running kernel's own driver code:
non-termination proven at 3/6/9 s + total guest lockup requiring QEMU
kill; bounded-walk fix returns immediately, verified on a rebuilt
module. Gate: machines with Tekram DC395/TRM-S1040 HBAs and a
misbehaving/malicious SCSI target (or bus glitch).

## 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.
