twa: unchecked CAM cdb_len overflows the 16-byte firmware CDB field (heap/DMA-pool overflow)
Summary
csio->cdb_len (u8, up to 255) is copied unvalidated into the common-layer request; the CL memcpy's it into the fixed 16-byte cdb[16] of the firmware command packet - up to 239 fully attacker-controlled bytes past the field into the controller's contiguous DMA command-packet pool, corrupting the packet's own SGL and adjacent in-flight commands that the firmware then reads/writes. Root/operator via pass(4) CAMIOCOMMAND; in-kernel periphs never exceed 16 (hence Medium). No 3ware card on guest (trigger builds+runs to no-SIM). Validate-cdb_len<=16 fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4654 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| twa_cdb.c | β | 3.0 KB | view raw | |
| run.log | β | 251 B | view raw | |
| env.txt | β | 271 B | view raw | |
| build.sh | β | 87 B | view raw | |
| run.sh | β | 94 B | view raw | |
| README.md | β | 1.6 KB | β raw | |
| VERDICT.md | β | 2.0 KB | β raw |
DF-4654 β twa CAM shim: unchecked cdb_len overflows 16-byte firmware CDB field
Files: sys/dev/raid/twa/tw_osl_cam.c:276-280 (feed) β tw_cl_io.c:124 (sink) β tw_cl_fwif.h:307-315 (struct tw_cl_command_9k: TW_UINT8 cdb[16]) Class: CWE-787/CWE-120 out-of-bounds write β Medium, certain (code), hardware-gated Verdict: NOT REPRODUCED on the audit guest (no 3ware 9000-series controller); defect proven by source trace + compiled trigger.
Trigger
twa_cdb.c: scans /dev/pass* via CAMIOCOMMAND XPT_PATH_INQ looking for a
SIM named "twa"; when found, issues XPT_SCSI_IO with csio.cdb_len = 255
(CAM_CDB_POINTER, 0x41-filled). tw_osli_execute_scsi() copies cdb_len
unchecked into scsi_req->cdb_len; tw_cl_start_io() then does
tw_osl_memcpy(cmd->cdb, scsi_req->cdb, scsi_req->cdb_len) into the
16-byte cdb[] of the firmware command packet β up to 239 fully
attacker-controlled bytes past the field, into the contiguous
bus_dmamem_alloc'd command-packet pool (tw_osl_freebsd.c:575):
corrupts the packet's own SGL and the following request packets, which
the controller then DMA-reads/writes (device-mediated memory corruption).
Guest result (run.log)
BUILD-OK; only SIM present is "ata" (QEMU DVD): "RESULT: no twa SIM present on this system" β the overflow path cannot execute without 3ware 9xxx hardware. Reachability on real iron: pass(4) CAMIOCOMMAND (root/operator) or any kernel CAM consumer issuing a >16-byte CDB.
Fix
Clamp in tw_osl_cam.c: reject csio->cdb_len > sizeof(cmd->cdb) (16) with CAM_REQ_INVALID before building scsi_req (see verdict.json fix).
DF-4654 β twa CAM shim: unchecked cdb_len overflows 16-byte firmware CDB field
Files: sys/dev/raid/twa/tw_osl_cam.c:276-280 (feed) β tw_cl_io.c:124 (sink) β tw_cl_fwif.h:307-315 (struct tw_cl_command_9k: TW_UINT8 cdb[16]) Class: CWE-787/CWE-120 out-of-bounds write β Medium, certain (code), hardware-gated Verdict: NOT REPRODUCED on the audit guest (no 3ware 9000-series controller); defect proven by source trace + compiled trigger.
Trigger
twa_cdb.c: scans /dev/pass* via CAMIOCOMMAND XPT_PATH_INQ looking for a
SIM named "twa"; when found, issues XPT_SCSI_IO with csio.cdb_len = 255
(CAM_CDB_POINTER, 0x41-filled). tw_osli_execute_scsi() copies cdb_len
unchecked into scsi_req->cdb_len; tw_cl_start_io() then does
tw_osl_memcpy(cmd->cdb, scsi_req->cdb, scsi_req->cdb_len) into the
16-byte cdb[] of the firmware command packet β up to 239 fully
attacker-controlled bytes past the field, into the contiguous
bus_dmamem_alloc'd command-packet pool (tw_osl_freebsd.c:575):
corrupts the packet's own SGL and the following request packets, which
the controller then DMA-reads/writes (device-mediated memory corruption).
Guest result (run.log)
BUILD-OK; only SIM present is "ata" (QEMU DVD): "RESULT: no twa SIM present on this system" β the overflow path cannot execute without 3ware 9xxx hardware. Reachability on real iron: pass(4) CAMIOCOMMAND (root/operator) or any kernel CAM consumer issuing a >16-byte CDB.
Fix
Clamp in tw_osl_cam.c: reject csio->cdb_len > sizeof(cmd->cdb) (16) with CAM_REQ_INVALID before building scsi_req (see verdict.json fix).
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.
(No fix.diff for this item: documented recommendation only - see Fix above.)
Fix verification
not_testablenot validated (no hardware); fix is a 4-line bounds check in tw_osli_execute_scsi
Confirmed kernel references
Detail
Exploit chain
operator/root -> camcontrol/CAMIOCOMMAND XPT_SCSI_IO with cdb_len>16 -> tw_osli_execute_scsi (no validation) -> tw_cl_start_io memcpy into cdb[16] -> SGL/packet corruption in DMA pool -> device-mediated kernel memory read/write
Evidence (decisive lines)
run.log (trigger build+run: 'no twa SIM present'); source trace tw_osl_cam.c:276-280 -> tw_cl_io.c:124 -> tw_cl_fwif.h:315
PoC changes
DFly specifics fixed vs seed: ccb_pathinq uses dev_name (not sim_name); CAMIOCOMMAND comes from scsi_pass.h; fixed comment nesting that broke the build
Verified recommended fix
In tw_osli_execute_scsi: if (csio->cdb_len > 16) { ccb_h->status = CAM_REQ_INVALID; xpt_done(ccb); return 1; }
Verdict
Code defect is certain: tw_osl_cam.c:280 copies csio->cdb_len (u_int8_t, up to 255, never validated) into scsi_req->cdb_len; tw_cl_io.c:124 memcpy's it into the 16-byte cdb[] field of struct tw_cl_command_9k (tw_cl_fwif.h:315), overflowing up to 239 controlled bytes into the contiguous DMA command-packet pool (tw_osl_freebsd.c:575) - corrupting this packet's SGL and adjacent packets that the firmware DMAs. Could not execute on the audit guest: trigger compiled and ran, but the only CAM SIM is 'ata' (QEMU DVD) - no 3ware 9000-series controller exists in QEMU. Reachability requires pass(4)/CAMIOCOMMAND (root/operator) on real hardware.
No comments yet.