# DF-1236 — trm SCSI Extended-Message MsgInBuf overflow

## Verdict (one line)
**CONFIRMED REAL (source trace + harness primitive), NOT reproduced on audit guest (no Tekram DC395 `trm` HBA).**

## Finding
`sys/dev/disk/trm/trm.c:trm_MsgInPhase0()` accumulates incoming SCSI
EXTENDED message bytes into `MsgInBuf[6]` (`sys/dev/disk/trm/trm.h:168`)
with no bound check, so a malicious SCSI **target** that sends an
EXTENDED message whose code byte is neither 1 (SDTR) nor 3 (WDTR) drives
`pMsgPtr` past the 6-byte buffer into `MsgOutBuf`, `MsgCnt`,
`TagNumber`, `SRBStatus`, and adjacent SRB heap.

## Mechanism (path:line)
1. `trm.c:1861-1868` — first `MSG_EXTENDED`(0x01) byte: sets
   `SRB_EXTEND_MSGIN`, `MsgInBuf[0]=01`, `MsgCnt=1`,
   `pMsgPtr = &MsgInBuf[1]`.
2. `trm.c:1958-1960` — every subsequent byte:
   `*pMsgPtr = code; MsgCnt++; pMsgPtr++;` **unconditionally, no bound**.
3. Termination exists only for `MsgInBuf[2]==3 && MsgCnt==4` (WDTR,
   `trm.c:2026`) and `MsgInBuf[2]==1 && MsgCnt==5` (SDTR, `trm.c:2113`).
4. A code byte ≠ {1,3} matches neither; control falls through
   `trm.c:2234` (returns with `PH_BUS_FREE`) leaving `SRB_EXTEND_MSGIN`
   set, so the next message-in byte is written at the now-advanced
   `pMsgPtr`. After 5 increments `pMsgPtr` reaches `MsgInBuf[6]` (one
   past the end) and then walks `MsgOutBuf[0..5]`, `AdaptStatus`,
   `TargetStatus`, `MsgCnt`, `TagNumber`, `SRBStatus`, … and into
   adjacent heap. The byte **values** are attacker-controlled (they are
   the message bytes emitted by the malicious target).

## Why not reproduced on the audit guest
`trm` is the Tekram DC395U/D/W SCSI host-adapter driver. The QEMU/KVM
audit guest has **no such HBA** and no SCSI target framework that can
emit the malicious message stream. `trm.ko` exists as a loadable module
(`/boot/kernel/trm.ko`) but is **not in `X86_64_GENERIC`** and, even if
`kldload`ed, finds no hardware to attach — `trm_MsgInPhase0` is dead at
runtime on this guest. Triggering requires a physical/emulated `trm`
HBA plus a malicious SCSI target (e.g. a malicious external SCSI/USB
device). This is a legitimate "malicious peripheral device" threat
model, but it is not exercisable here.

## Primitive proof (harness)
`harness.c` replicates the SRB layout and the accumulation loop byte-for-byte
and feeds a malicious stream (length=0xff, code=0x02). Result on the guest:

```
Bytes written past end of MsgInBuf[6]: 59
MsgOutBuf after overflow: a5 a6 a7 a8 a9 aa
AdaptStatus=0xab TargetStatus=0xac TagNumber=0xae SRBStatus=0xaf
PRIMITIVE CONFIRMED: attacker-controlled bytes written past MsgInBuf[6]
into MsgOutBuf and beyond (SRB heap fields). Bug is REAL.
```

This proves the write primitive is real, decoupled from the HBA
dependency.

## Fix
`fix.diff` adds a bound check on `pMsgPtr` against `MsgInBuf` in the
extended-message accumulation branch (`trm.c`): if the pointer has
reached the end of the buffer, the driver rejects the malformed message
(MSG_REJECT + ATN) and clears `SRB_EXTEND_MSGIN` instead of writing past
the buffer. **Validated: builds cleanly into `trm.ko` with `-Werror`
(DragonFly gcc 8.3).**

## Reproduce
```
ssh dfbsd-maxx   # unprivileged
cd poc/DF-1236 && cc -O2 -Wall -o harness harness.c && ./harness
```
