β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-1236

Extended SCSI message accumulation overflows MsgInBuf[6] into adjacent SRB pointer fields

Summary

trm_MsgInPhase0 at trm.c:1958-1960: *pSRB->pMsgPtr=message_in_code; pMsgPtr++ with NO bound check vs MsgInBuf[6] (trm.h:168). Only MsgCnt==4(WDTR) and ==5(SDTR) with code 1/3 branch out. Malicious target sends MSG_EXTENDED+len 0xFF+code X(not 1/3)+0xFF bytes: pMsgPtr walks past MsgInBuf into MsgOutBuf/AdaptStatus/crosses into SRB[tag+1] pointer fields (pNextSRB/pSRBDCB/pSRBSGL/pccb). SRBs are contiguous DMA allocation. No local priv needed - just bus access. Fix: check pMsgPtr>=&MsgInBuf[sizeof] before write.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1236 Β· 11 files
FileTypeDescriptionSize
harness.c trigger-source userspace replication of trm_MsgInPhase0 extended-message accumulation; proves MsgInBuf[6] overflow 5.0 KB view raw
build.sh build-script cc -O2 -Wall -o harness harness.c 222 B view raw
run.sh run-script ./harness 111 B view raw
run.log run-log harness output: 59 bytes past MsgInBuf, MsgOutBuf corrupted 451 B view raw
fix.diff suggested-fix bounds pMsgPtr against MsgInBuf in trm.c accumulation branch 937 B view raw
fix_build.log build-log trm.ko builds clean with -Werror (fix compiles) 870 B view raw
env.txt environment uname, cc, module list 346 B view raw
README.md readme how to reproduce 1.1 KB ↓ raw
VERDICT.md verdict full analysis 3.2 KB ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme how to reproduce
↓ download raw

DF-1236 β€” reproduction

What this is

A userspace harness (harness.c) that replicates the vulnerable trm_MsgInPhase0 extended-message accumulation logic (sys/dev/disk/trm/trm.c:1958-1960) and proves the MsgInBuf[6] overflow primitive against a malicious SCSI target byte stream.

The live kernel trigger additionally requires a Tekram DC395 trm HBA plus a malicious SCSI target sending crafted EXTENDED messages β€” hardware absent from the QEMU/KVM audit guest, so the kernel OOB is not exercisable here. The harness proves the logic flaw and the write primitive.

Build & run (as the unprivileged user)

./build.sh    # cc -O2 -Wall -o harness harness.c
./run.sh      # ./harness

Expected output

DF-1236 trm MsgInBuf overflow harness
MsgInBuf is 6 bytes (trm.h:168); pMsgPtr started at MsgInBuf[1]
Bytes written past end of MsgInBuf[6]: 59
...
PRIMITIVE CONFIRMED: attacker-controlled bytes written past MsgInBuf[6]
into MsgOutBuf and beyond (SRB heap fields). Bug is REAL.

Fix

fix.diff β€” bounds pMsgPtr against MsgInBuf in the accumulation branch. Builds cleanly into trm.ko (-Werror). See VERDICT.md.

VERDICT.md verdict full analysis
↓ download raw

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 kldloaded, 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

Fix verification

not_testable

compile+harness validated

module build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source+harness. trm_MsgInPhase0 extended SCSI msg accumulation overflows MsgInBuf[6] -> 59B OOB into SRB. trm not in GENERIC.