# DF-1311 — hptiop_post_req_itl stack buffer overflow (HighPoint RocketRAID)

## Verdict
**NOT TESTABLE AT RUNTIME on this guest — confirmed real latent vulnerability in source.**

The bug is genuine and the analysis is certain, but the vulnerable I/O path can
only execute on a machine with a **HighPoint RocketRAID 3xxx (ITL/IOP) HBA**,
which the QEMU audit guest does not have.

## Mechanism (confirmed by source trace)
`sys/dev/raid/hptiop/hptiop.c:2401` `hptiop_post_req_itl()` is the ITL-family
firmware SCSI-command submission callback.  In the
`HPT_SRB_FLAG_HIGH_MEM_ACESS` branch (line 2417) it builds the request in a
**stack-local** `struct hpt_iop_request_scsi_command req;`.

That struct (`sys/dev/raid/hptiop/hptiop.h:301`) contains:
```c
u_int8_t cdb[16];
...
struct hpt_iopsg sg_list[1];   /* only ONE scatter/gather slot */
```

- **Scatter/gather overflow:** line 2432-2440 loops `idx < nsegs`, advancing a
  `psg` pointer into `req.sg_list` and writing `pci_address`/`size`/`eot` per
  segment.  `nsegs` comes from `bus_dmamap_load` and is bounded only by
  `hba->max_sg_count` (set verbatim from HBA firmware `iop_config.max_sg_count`
  at line 1933, with no upper clamp).  A typical HBA reports 30+ segments, so
  any multi-segment transfer writes `nsegs-1` 16-byte `struct hpt_iopsg` entries
  past the 1-entry stack array → **kernel stack overflow**.
- **CDB overflow:** line 2442 `bcopy(cdb, req.cdb, ccb->csio.cdb_len)` copies
  `cdb_len` (up to `MAX_CDBLEN`=16 via CAM, but controllable through the CDB
  pointer path) into `cdb[16]` with no length check → off-by/overflow of `cdb`.

`hptiop` **is compiled statically into `X86_64_GENERIC`** (`device hptiop`), but
the function is dead code unless the driver actually attaches to a HighPoint PCI
device — which requires the physical HBA.

## Why it does not reproduce on this guest
- `pciconf -l`: the only PCI devices are i440FX/PIIX3/virtio and a QEMU std-VGA
  (`1234:1111`).  No HighPoint RAID controller is present.
- `dmesg` shows no `hptiop` attach.  `nm /boot/kernel/kernel | grep -c hptiop`
  shows the code is *linked* (81 symbols) but never *executed*.
- No CAM bus for hptiop exists, so no userspace `ioctl`/`pass`/`da` path can
  deliver a CCB to `hptiop_post_req_itl`.  This is "needs specific HW" (case d).

## Severity / realistic ceiling
On a host with a HighPoint RocketRAID 3xxx HBA, this is a kernel stack buffer
overflow reachable by ordinary multi-segment disk I/O (no privilege beyond
access to a disk on the HBA).  Worst case is kernel stack corruption → panic
or potential code execution depending on what the overflowed `sg_list`/`cdb`
overwrite (saved frame pointer / return address are within reach for large
`nsegs`).  The CVSS in the finding (AV:L/AC:L/PR:L) is appropriate.

## Fix (see fix.diff)
1. Clamp `hba->max_sg_count` to a compile-time `HPTIOP_MAX_SG_COUNT` (64) at
   attach so an absurd firmware value can't blow the stack buffer.
2. Replace the fixed 1-entry stack struct with a stack byte-buffer sized for
   `HPTIOP_MAX_SG_COUNT` scatter/gather entries, accessed via a pointer.
3. Bound the `cdb` `bcopy` to `sizeof(req->cdb)`.

This is compiled-and-boot-validated on GENERIC (see build.log / fix_build.log);
runtime behaviour cannot be exercised without the HBA.

## Note on the brief's "mpr SAS" label
The job brief mislabeled DF-1298 as "mpr SAS"; DF-1298 is actually the
amdgpu/display `bios_parser.c`.  DF-1311 (this finding) is the HighPoint RAID
driver `hptiop`.  `mpr` is a different finding not in this batch.
