DragonFlyBSD Kernel Audit
DF-1237 / trm_sg_overflow.c
← back to finding ↓ download raw
/*
 * 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);
}