# DF-1285 — hptmv OsSendCommand writes fixed-size replies past small dxfer_len buffer

## Finding
`OsSendCommand` at `sys/dev/raid/hptmv/entry.c:2678` handles three SCSI CDB
types by writing fixed-size replies directly into `ccb->csio.data_ptr`:

- **INQUIRY** (`entry.c:2709`) — `SetInquiryData()` fills
  `sizeof(INQUIRYDATA)` (= 96 bytes, defined in `osbsd.h:68-90`) into the
  buffer.
- **READ_CAPACITY** (`entry.c:2715`) — writes 8 bytes via `rbuf[0..7]`.
- **SERVICE_ACTION_IN (0x9e)** (`entry.c:2740`) — writes 12 bytes via
  `rbuf[0..11]`.

CAM's `cam_periph_mapmem` allocates the kernel bounce buffer at exactly
`dxfer_len` bytes (the user-specified transfer length). If the user issues
one of these CDBs with a smaller `dxfer_len` than the reply (e.g. `dxfer_len=4`
for INQUIRY), the writes overflow the allocation by 4..92 bytes.

The INQUIRY data is partially attacker-influenced on RAID arrays (array
membership strings from `pVDev->VDeviceType` flow into the
`VendorId`/`ProductId`/`ProductRevisionLevel` memcpy's at `entry.c:2595-2620`);
the READ_CAPACITY / SERVICE_ACTION_IN values are derived from
`pVDev->VDeviceCapacity` (disk size). The overflow bytes therefore are *not*
fully attacker-shaped, but the start of the overwrite is a fixed pattern
("RR18xx  ", "3.00", etc.) and the size is controlled.

## Fix
Validate `csio->dxfer_len` against the actual reply size before writing, and
return `CAM_REQ_INVALID` if the buffer is too small. Do this in each of the
three cases.

## Note on the file vs the brief
The brief calls this "hptrr" — that is wrong. The vulnerable file is
`sys/dev/raid/hptmv/entry.c` (the **hptmv** driver — Highpoint RocketRAID
182x). The DB row's `file` column is correct.

## Verification on this guest
- The hptmv driver is statically compiled in (`device hptmv` in
  `sys/config/X86_64_GENERIC:119`) and shows up in `kldstat -v`
  (`pci/hptmv`).
- The QEMU guest has **no Marvell 88SX508x / Highpoint PCI device**
  (`pciconf -l` shows only i440FX/PIIX/ACPI/virtio-net/virtio-blk/std-VGA).
  `hptmv_probe` never matches, so `hptmv_attach` and the
  `xpt_bus_register` -> `OsSendCommand` path never run. The bug is **not
  runtime-triggerable on this guest**.
- Source-level confirmation:
  - `osbsd.h:68-90` — `INQUIRYDATA` is 96 bytes (5 + 1 + 1 + 8 + 16 + 4 + 20 + 40 + 1).
  - `entry.c:2710-2711` — `ZeroMemory(data_ptr, dxfer_len)` then
    `SetInquiryData` writes the full struct.
  - `entry.c:2717-2734` — READ_CAPACITY writes 8 bytes via `rbuf[0..7]`.
  - `entry.c:2742-2756` — SERVICE_ACTION_IN writes 12 bytes via `rbuf[0..11]`.
- Fix verified to compile (combined build with DF-1278/1279/1280/1287).

## Realistic impact ceiling
Local-user-controllable heap OOB write of 4..92 bytes if an hptmv-managed
disk is exposed to a low-privileged user via the CAM `pass(4)` device or a
filesystem on top of an hptmv disk. The byte pattern at the overwrite start
is fixed ("RR18xx  " or zero from `ZeroMemory`) — i.e. not fully
attacker-shaped, but the size is. Slab layout is unknown until triggered.
