# DF-4559 VERDICT — reproduced (harness), High, OOB heap write in mps IR volume registration

## Bottom line

`sassc->targets[]` is allocated with `sc->facts->MaxTargets` entries
(sys/dev/raid/mps/mps_sas.c:696-697) while the mapping layer legitimately
hands out target IDs up to `sc->max_devices - 1 =
facts->MaxTargets + facts->MaxVolumes - 1` (sys/dev/raid/mps/mps_mapping.c:1733-1734,
:232-234). In HIGH IR-volume-mapping mode every RAID volume ID indexes
past the end of the array. Both RAID-volume registration sinks live in the
file under audit and write there: `mpssas_volume_add()`
(sys/dev/raid/mps/mps_sas_lsi.c:847-853: `tid`, fw u16 `handle`,
**fw-controlled u64 `devname = wwid`**, `TAILQ_INIT`/`SLIST_INIT` NULL
pointer pairs) and the IR CONFIG CHANGE REMOVED branch
(sys/dev/raid/mps/mps_sas_lsi.c:310-316: six zeroing writes), plus the
OOB `targetid = targ - sassc->targets` computation fed into CAM
(sys/dev/raid/mps/mps_sas.c:285 via mpssas_rescan_target from
mps_sas_lsi.c:317/:855).

## Why it reproduces (evidence)

Guard-page harness on the DragonFly 6.5-DEVELOPMENT guest (run.log,
run.2.log — two consecutive runs, identical):

- voladd-HIGH: the write sequence of mps_sas_lsi.c:848-853 at
  `id = max_devices - max_volumes = MaxTargets` SIGSEGVs on the guard page
  — the write begins at byte `n*sizeof(mpssas_target)` of an
  `n*sizeof(mpssas_target)`-byte allocation: unambiguously past the end.
- removed-HIGH: zeroing writes of :311-316 at `id = max_devices-1` fault
  1600 bytes past the end.
- voladd-LOW control: clean — proves the trigger is exactly the ID-range
  mismatch, not the write sequence.
- Canary: 416 bytes corrupted past a 51200-byte allocation
  ([+51200..+52679]); readback of `devname` at +51208 returns the
  fw-supplied u64 verbatim — the controlled-write primitive is real.

## Threat model / reachability

- The gate is IOC page 8 `IRVolumeMappingFlags` selecting HIGH volume
  mapping plus any IR volume event (volume created / comes online
  (mps_sas_lsi.c:288/:406), or removed (:296-317)). That is a *supported,
  operator-selectable* configuration on LSI IR firmware — the corruption
  fires during normal discovery on such boxes, no malicious input needed.
- In the malicious-firmware threat model (same one DF-1696/1697 use), the
  fw fully controls the ID (mapping table) and the 8-byte `wwid` payload.
- What stops short of uid=0: the write content is constrained (fixed
  offsets inside `struct mpssas_target`, value set = {bounded id, fw u16
  handle, fw u64 wwid, NULLs, zeros}) and the overflow distance is
  `k*sizeof(mpssas_target)` for k < MaxVolumes — adjacent-heap corruption
  of whatever follows the targets allocation, panic-grade in practice.
  The guest has no mps HBA, so an end-to-end in-driver escalation chain
  cannot be demonstrated on this hardware; per the DF-4363/DF-4013
  precedent the primitive is proven by the byte-exact harness.

## Root cause (path:line)

- sys/dev/raid/mps/mps_sas.c:696-697 — allocation sized
  `sc->facts->MaxTargets`.
- sys/dev/raid/mps/mps_mapping.c:1733-1734 — ID space is
  `MaxTargets + MaxVolumes` (`sc->max_devices`).
- sys/dev/raid/mps/mps_mapping.c:232-234 — HIGH volume mapping puts volume
  IDs at the top of that space.
- sys/dev/raid/mps/mps_sas_lsi.c:847-853 and :310-317 — the OOB sinks.
- sys/dev/raid/mps/mps_sas.c:181 — `find_target_by_handle` scanning only
  `[0, MaxTargets)` corroborates the divergence (volumes are invisible to
  the "already added" check at mps_sas_lsi.c:400).

## Fix validation

`fix.diff` sizes `sassc->targets` with `sassc->maxtargets =
facts->MaxTargets + facts->MaxVolumes` and uses it for the by-handle scan.
Harness arm `voladd-HIGH-FIXED` re-runs the identical write sequence
against the fixed sizing: clean exit, zero canary clobber — the
previously-observed OOB write is gone (baseline vs patched in run.log).

## Notes

- The informational harness arm also documents the `max_devices` u16
  truncation corner (MaxTargets=65535/MaxVolumes=255 → `max_devices=254`
  → `start_idx` wraps to 0xFFFFFFFF at mps_sas_lsi.c:901): malicious-fw
  only, wild `mapping_table[0xffffffff]` read at shutdown; folded into
  this pack's notes rather than filed separately (absurd facts values).
- Guest dirtied only with /root harness binaries; guest reset (with-src)
  performed after the run.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
