DF-1237 / trm_sg_overflow.c
/* * DF-1237 — trm_ExecuteSRB unbounded scatter/gather copy proof-of-concept * * Bug (sys/dev/disk/trm/trm.c): * Lines 434-440: copy loop in trm_ExecuteSRB * psg = pSRB->pSRBSGL; * while (dm_segs < end_seg) { * psg->address = dm_segs->ds_addr; * psg->length = dm_segs->ds_len; * psg++; dm_segs++; * } * pSRBSGL is a DMA-coherent allocation sized TRM_MAX_SG_LISTENTRY=32 * entries (trm.h:92, trm.c:3498). nseg is uncapped -> OOB write of * adjacent DMA-coherent slab. Also: buffer_dmat is created with * nsegments=TRM_NSEG = btoc(MAXPHYS)+1 = 33 (trm.h:98, trm.c:3429), * so even the legitimate bus_dmamap_load path can produce 33 segments * and overflow by 1 entry (8 bytes). * * Lines 666-669: CAM_SCATTER_VALID path: * segs = (struct bus_dma_segment *) pcsio->data_ptr; * trm_ExecuteSRB(pSRB, segs, pcsio->sglist_cnt, 1); * sglist_cnt is u_int16_t 0..65535 from userspace -- COMPLETELY * uncapped. pass(4) with CAM_SCATTER_VALID can pass any value. * * Privilege: any local user with write access to /dev/passN (operator * group on stock devfs) AND a Tekram DC-395U/UW controller. * * THIS GUEST: trm not in kernel, no Tekram controller. PoC prints * reachability status. */ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> int main(void) { printf("[DF-1237] trm_ExecuteSRB unbounded SG copy demonstrator\n"); printf("[DF-1237] Bug: trm.c:434-440 SG copy loop has no nseg cap vs\n"); printf("[DF-1237] pSRBSGL[TRM_MAX_SG_LISTENTRY=32];\n"); printf("[DF-1237] trm.c:668-669 passes sglist_cnt (u16, up to 65535)\n"); printf("[DF-1237] straight through as nseg with no bounds check.\n\n"); if (system("kldstat -v 2>&1 | grep -qi 'trm'") == 0) { printf("[DF-1237] trm driver IS loaded.\n"); printf("[DF-1237] A pass(4) XPT_SCSI_IO with sglist_cnt > 32 would overflow pSRBSGL.\n"); } else { printf("[DF-1237] trm driver NOT loaded (no 'device trm' in X86_64_GENERIC).\n"); printf("[DF-1237] trm_ExecuteSRB is dead code on this kernel.\n"); } printf("[DF-1237] Source-level verification only (see VERDICT.md).\n"); return (0); } |