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)
PoC verification
Evidence pack
findings/poc/DF-1236 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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 |
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.
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)
trm.c:1861-1868β firstMSG_EXTENDED(0x01) byte: setsSRB_EXTEND_MSGIN,MsgInBuf[0]=01,MsgCnt=1,pMsgPtr = &MsgInBuf[1].trm.c:1958-1960β every subsequent byte:*pMsgPtr = code; MsgCnt++; pMsgPtr++;unconditionally, no bound.- Termination exists only for
MsgInBuf[2]==3 && MsgCnt==4(WDTR,trm.c:2026) andMsgInBuf[2]==1 && MsgCnt==5(SDTR,trm.c:2113). - A code byte β {1,3} matches neither; control falls through
trm.c:2234(returns withPH_BUS_FREE) leavingSRB_EXTEND_MSGINset, so the next message-in byte is written at the now-advancedpMsgPtr. After 5 incrementspMsgPtrreachesMsgInBuf[6](one past the end) and then walksMsgOutBuf[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_testablecompile+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.
No comments yet.