# DF-4174 — iir(4) unbounded physical scatter/gather copy (pass(4)-reachable heap overflow)

## Build

    # on a DragonFly guest:
    cc -O -Wall -o sg_overflow sg_overflow.c -lcam

## Run

    ./sg_overflow [pass-device]     # default /dev/pass0

The PoC opens the pass device, verifies via XPT_PATH_INQ that it sits on an
**iir** bus, and then sends an XPT_SCSI_IO CCB with
`flags = CAM_DIR_IN | CAM_SCATTER_VALID | CAM_SG_LIST_PHYS` and
`sglist_cnt = 64` (GDT_MAXSG is 32) — reproducing exactly the path
`gdt_raw_cmd()` iir.c:843-878 → `gdtexecuteccb()` iir.c:1254-1285 that copies
`nseg` entries into the fixed 32-entry SG array at the tail of the 324-byte
`gccb->gc_cmd[]`.

## Expected output

* On a host **with** iir hardware (as root): kernel heap corruption
  immediately past `gccb->gc_cmd[]` into `struct gdt_ccb` fields and the
  neighbouring gccbs of the `kmalloc`'d `sc_gccbs[]` block (panic or silent
  corruption). The write content is attacker-chosen segment addresses/lengths.
* On the audit guest (no iir controller): the SIM check trips —
  `/dev/pass0 sits on SIM "ata"` → `[!] SIM is not "iir"` → exit 4.
  This is the honest hardware gate; see `run.log` and `gate_check.log`.

## Fix
`fix.diff` rejects `sglist_cnt > GDT_MAXSG` physical SG lists in `gdt_next()`
(same place the driver already rejects `cdb_len > 12`).
