DragonFlyBSD Kernel Audit
DF-1235 / trm_cdb_overflow.c
← back to finding ↓ download raw
/*
 * DF-1235 — trm_action XPT_SCSI_IO unbounded CDB copy proof-of-concept
 *
 * Bug (sys/dev/disk/trm/trm.c):
 *   Line 591: pSRB->ScsiCmdLen = pcsio->cdb_len;       (u_int8_t 0..255)
 *   Line 598-599 / 609-610:
 *       bcopy(cdb_ptr_or_bytes, pSRB->CmdBlock, pcsio->cdb_len);
 *
 * CmdBlock is `u_int8_t CmdBlock[12]` (sys/dev/disk/trm/trm.h:145).
 * SCSI_MAX_CDBLEN is 16. There is NO bounds check: a 16-byte CDB
 * (READ_16/WRITE_16 issued by da(4) on a >2TB disk) writes 4 bytes
 * past the end of CmdBlock into Segment0. Via the CAM_CDB_POINTER
 * path with pass(4), cdb_len can be up to 255, overflowing into
 * pNextSRB / pSRBDCB / pSRBSGL / pccb pointers (struct _SRB layout,
 * trm.h:144-160) -> type confusion / UAF / control-flow hijack.
 *
 * Privilege: any local user with write access to a /dev/passN node
 * (operator group on stock devfs) AND a Tekram DC-395U/UW host adapter.
 *
 * THIS GUEST: trm driver is NOT compiled into the kernel
 * (sys/config/X86_64_GENERIC has no `device trm`), and there is no
 * Tekram controller. The XPT_SCSI_IO path through trm_action is dead
 * on this guest. 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-1235] trm_action unbounded CDB copy demonstrator\n");
    printf("[DF-1235] Bug: trm.c:598-599 / 609-610 bcopy cdb_len -> CmdBlock[12]\n");
    printf("[DF-1235]      with NO bounds check; cdb_len is u8 (0..255).\n");
    printf("[DF-1235]      SCSI_MAX_CDBLEN=16 > sizeof(CmdBlock)=12.\n\n");

    /* Test if trm is in the kernel (loaded module or static). */
    if (system("kldstat -v 2>&1 | grep -qi 'trm'") == 0) {
        printf("[DF-1235] trm driver IS loaded.\n");
        printf("[DF-1235] A pass(4) XPT_SCSI_IO with cdb_len=16+ would overflow CmdBlock.\n");
    } else {
        printf("[DF-1235] trm driver NOT loaded (no 'device trm' in X86_64_GENERIC).\n");
        printf("[DF-1235] trm_action is dead code on this kernel.\n");
    }
    printf("[DF-1235] Source-level verification only (see VERDICT.md).\n");
    return (0);
}