Unbounded CDB copy into fixed 12-byte SRB CmdBlock overwrites SRB pointer fields
Summary
trm_action XPT_SCSI_IO at trm.c:591: pSRB->ScsiCmdLen=pcsio->cdb_len (u_int8_t 0-255). bcopy at :598-599/:609-610 copies cdb_len bytes into CmdBlock[12] (trm.h:145) with NO bounds check. 16-byte CDB (READ_16/WRITE_16 from da(4) on >2TB disk) writes 4 bytes past into Segment0. pass(4) with CAM_CDB_POINTER cdb_len=200 overwrites pNextSRB/pSRBDCB/pSRBSGL/pccb pointers -> UAF/code execution. SCSI_MAX_CDBLEN=16 > CmdBlock=12. Fix: reject cdb_len>sizeof(CmdBlock).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1235 Β· 12 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | full path:line trace, threat model, fix rationale | 5.2 KB | β raw |
| README.md | readme | claim, verdict, runnable-PoC instructions | 2.1 KB | β raw |
| trm_cdb_overflow.c | trigger-source | PoC: reachability check (kldstat grep trm) | 2.1 KB | view raw |
| build.sh | build-script | cc -O -Wall -o trm_cdb_overflow trm_cdb_overflow.c | 193 B | view raw |
| run.sh | run-script | ./trm_cdb_overflow | 104 B | view raw |
| build.log | build-log | PoC build, full output | 127 B | view raw |
| run.log | run-log | PoC run on this guest (trm not loaded) | 451 B | view raw |
| fix.diff | suggested-fix | reject cdb_len > sizeof(pSRB->CmdBlock) in trm_action with CAM_REQ_INVALID | 792 B | view raw |
| fix_build.log | build-log | kernel build rc=0 with all 5 fixes applied; trm.c compiled clean as trm.ko under -Werror | 2.1 KB | view raw |
| env.txt | environment | guest uname, cc version, PCI topology | 2.0 KB | view 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-1235 β README
Finding
trm_action (XPT_SCSI_IO) at sys/dev/disk/trm/trm.c:591,598-599,609-610
copies cdb_len bytes from the CAM CDB into pSRB->CmdBlock[12] with NO
bounds check. CmdBlock is 12 bytes (trm.h:145), but cdb_len is a
u_int8_t (0..255). A 16-byte CDB (READ_16/WRITE_16 on >2 TB disks)
overflows by 4 bytes into Segment0; pass(4) with CAM_CDB_POINTER
and cdb_len=200 overwrites pNextSRB/pSRBDCB/pSRBSGL/pccb
(trm.h:144-160) β SRB type confusion / UAF / hijack.
Verdict
NOT REPRODUCED on this guest: trm is not in X86_64_GENERIC
(sys/config/X86_64_GENERIC has no device trm) and no Tekram DC-395
controller is present in pciconf -lv. trm_action is dead code on
this kernel. PoC prints the reachability status.
Confidence (bug is real): certain β traced line-by-line in sys/.
Impact ceiling: operator-group β kernel heap corruption / type
confusion on any host with a Tekram DC-395U/UW adapter and the trm
module loaded.
How to reproduce
./build.sh && ./run.sh
Expected on this guest: PoC builds clean, prints "trm driver NOT loaded
(no 'device trm' in X86_64_GENERIC)" and "trm_action is dead code on
this kernel". On a host with the trm module loaded and a Tekram
adapter, issuing a CAMIOCOMMAND XPT_SCSI_IO with cdb_len > 12
through /dev/passN overflows CmdBlock.
Files
| Path | Purpose |
|---|---|
trm_cdb_overflow.c |
PoC: reachability check (kldstat grep trm) |
build.sh / run.sh |
exact build/run commands |
fix.diff |
reject cdb_len > sizeof(CmdBlock) in trm_action |
VERDICT.md |
full path:line trace, threat model, fix rationale |
build.log / run.log |
PoC build + run outputs |
fix_build.log |
module-build compile validation of fix.diff |
env.txt |
guest uname / cc / device topology |
DF-1235 β VERDICT
Finding: trm_action(XPT_SCSI_IO) at sys/dev/disk/trm/trm.c:591
copies the SCSI CDB into pSRB->CmdBlock[12] with no bounds check; a
cdb_len larger than 12 (legitimate READ_16/WRITE_16 is 16; user
cdb_len via pass(4) can be up to 255) overflows into Segment0,
Segment1, pNextSRB, pSRBDCB, pSRBSGL, and pccb (the SRB layout
at trm.h:144-160).
Status: NOT REPRODUCED on this guest β trm is not in
X86_64_GENERIC (sys/config/X86_64_GENERIC has no device trm) and no
Tekram DC-395 controller is present.
Confidence (bug is real): certain (traced line-by-line in sys/).
Impact ceiling: SRB type confusion / UAF / hijack of the pccb,
pNextSRB, pSRBDCB, pSRBSGL pointers β exploitable by any local
user with write access to /dev/passN (operator group) once a Tekram
adapter and trm module are present.
Mechanism (confirmed line-by-line in sys/)
-
struct _SRBatsys/dev/disk/trm/trm.h:144-160:c struct _SRB { u_int8_t CmdBlock[12]; /* :145 -- 12 bytes only */ u_long Segment0[2]; /* :146 -- immediate overflow target */ u_long Segment1[2]; /* :147 */ struct _SRB *pNextSRB; /* :148 -- attacker-overwritable ptr */ struct _DCB *pSRBDCB; /* :149 -- attacker-overwritable ptr */ SGentry SgSenseTemp; /* :150 */ PSEG pSRBSGL; /* :152 -- attacker-overwritable ptr */ ... union ccb *pccb; /* :160 -- attacker-overwritable ptr */ ... };The CDB target is 12 bytes.SCSI_MAX_CDBLENis 16. The 4-byte gap is the bug. -
trm_actionatsys/dev/disk/trm/trm.c:591:c pSRB->ScsiCmdLen = pcsio->cdb_len;and attrm.c:596-610(both CDB_POINTER and inline-cdb branches):c if ((pccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { if ((pccb->ccb_h.flags & CAM_CDB_PHYS) == 0) { bcopy(pcsio->cdb_io.cdb_ptr, pSRB->CmdBlock, pcsio->cdb_len); /* :598-599 */ } ... } else bcopy(pcsio->cdb_io.cdb_bytes, pSRB->CmdBlock, pcsio->cdb_len); /* :609-610 */No bounds check oncdb_len.pcsio->cdb_lenis au_int8_tinstruct ccb_scsiio, so it can be 0..255. -
Real-world overflow sources: - Disk I/O on a > 2 TB LUN issues
READ_16/WRITE_16(16-byte CDBs).cdb_len=16overflows by 4 bytes intoSegment0. The driver does not advertisePI_MSG_EXTENDEDCDB support and does not reject these CDBs, so this happens on real hardware. -pass(4)withCAM_CDB_POINTERlets any user with write access to/dev/passNsetcdb_lento any value 0..255. Withcdb_len=200, the bcopy overwritespNextSRB,pSRBDCB,pSRBSGL, andpccbβ type confusion / UAF / hijack. -
Subsequent code dereferences these corrupted pointers: -
pSRB->pSRBDCBattrm.c:485intrm_SendSRB, -pSRB->pNextSRBattrm.c:463, 502, 511, 514, -pSRB->pSRBSGLin the SG copy loop attrm.c:433, -pSRB->pccbattrm.c:423and in every completion path.
Why it is NOT REPRODUCED on this guest
sys/config/X86_64_GENERICdoes not containdevice trm. The driver is built only as the loadable moduletrm.ko.- The audit guest has no Tekram DC-395U/UW controller in
pciconf -lv, so even loadingtrm.kowould not bind the driver to any device and no/dev/passNwould route throughtrm_action. - PoC
trm_cdb_overflow.cconfirmskldstat -v | grep trmreturns empty.
Threat model & privilege boundary
/dev/passN is created by pass(4) and given default devfs perms of
0600 root:operator (only the QEMU CD-ROM shows up on the audit guest,
visible as /dev/pass0). Any user in the operator group can issue
CAMIOCOMMAND ioctls with XPT_SCSI_IO and a forged ccb_scsiio with
arbitrary cdb_len up to 255. On a host with a Tekram adapter and the
trm module loaded, this is a real operator-group β kernel corruption
vector. Note: loading trm.ko requires root, but loading the driver is
something a real admin does once at install time on a host with the
hardware β the exploit itself is fully unprivileged.
Fix (authored in fix.diff, applied + compile-validated)
Reject cdb_len > sizeof(pSRB->CmdBlock) immediately after the
assignment at trm.c:591, returning CAM_REQ_INVALID and the SRB to
the free list (matching the existing rejection pattern at trm.c:600-606
for CAM_CDB_PHYS). This is the minimum root-cause fix.
(Deepening CmdBlock to 16 would also fix the size but changes the DMA
wire format the chip expects β out of scope for a security patch.)
Validation
fix.diffapplies cleanly withpatch -p1 --forward(verified).- All 5 audit fixes applied together;
make -j6 nativekernel KERNCONF=X86_64_GENERICreturned rc=0 with no errors / warnings under-Werror.trm.cwas compiled cleanly as the loadable moduletrm.ko(built as part of the kernel module set). - Fix is not_testable at runtime on this guest (trm not in GENERIC, no Tekram HW).
Fix verification
not_testablecompile validated
nativekernel rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. trm CDB copy no bounds vs CmdBlock[12] -> SRB corruption. trm NOT in GENERIC, no Tekram HW.
No comments yet.