# DF-1282 — OOB heap write via unchecked firmware-controlled DeviceIndex in `_mapping_process_dpm_pg0`

**File:** `sys/dev/raid/mpr/mpr_mapping.c:2251` (sink: `:2327`, `:2358`)
**Class:** CWE-787 Out-of-bounds Write (heap)
**Severity:** High

## The bug (source-confirmed)

`_mapping_process_dpm_pg0()` reads firmware/hardware-controlled device
mapping entries out of the HBA's persistent DPM table. At `mpr_mapping.c:2251`:

```c
dev_idx = le16toh(dpm_entry->DeviceIndex);   /* u32, 0..65535, from firmware */
```

`dev_idx` is then used to index `sc->mapping_table[]`, which is allocated for
`sc->max_devices` entries at `:2140` (`max_devices = MaxTargets + max_volumes`,
`:2565`, typically ~264).

- **IR firmware path (`:2260-2272`):** bounds-checks `dev_idx >= start_idx && dev_idx <= end_idx`. SAFE.
- **Enclosure/Slot path (`:2327`):** `mt_entry = &sc->mapping_table[dev_idx];` then a
  loop writes `num_slots` consecutive entries (`:2328`). **NO bounds check.**
- **Device Persistence path (`:2358`):** `mt_entry = &sc->mapping_table[map_idx];`
  where `map_idx = dev_idx`. **NO bounds check.**

A malformed/persistent DPM entry (written by malicious HBA firmware or a
malicious SAS device whose mapping the controller persists) with
`DeviceIndex >= max_devices` therefore causes an out-of-bounds heap write past
the `mapping_table` allocation, writing attacker-shaped fields
(`physical_id`, `phy_bits`, `device_info`, `dpm_entry_num`, ...) over the
adjacent slab object(s).

## Reachability / threat model

The `mpr` driver attaches to LSI/Avago SAS2/SAS3 HBAs. **No such HBA is
present in the audit QEMU guest** (only virtio devices), so the path is not
runtime-reachable here — see `VERDICT.md`. The bug is a real latent defect
triggered by a malicious peripheral / malicious firmware / a malicious VM
passed-through to an HBA, or by NVRAM corruption on the controller. This
harness proves the primitive at the object level.

## Reproduce (harness)

```sh
./build.sh   # cc -O2 -o harness harness.c
./run.sh     # prints BUG CONFIRMED + adjacent-slab corruption, then the fix path
```

Expected output (decisive lines):
```
[DF-1282] BUG CONFIRMED: dev_idx=266 >= max_devices=264 -> write at mapping_table[266] is 64 bytes PAST the allocation (into the adjacent slab object)
[DF-1282] guard/slab region corrupted: YES -> next heap object(s) overwritten (4 of 64 entries touched)
```

## Fix

`fix.diff` adds a bounds check (`dev_idx >= sc->max_devices` and
`dev_idx + num_slots <= sc->max_devices`) before indexing in both the
Enclosure/Slot path and the Device Persistence path, mirroring the check the IR
path already has. Validated: applies cleanly and the `mpr` module compiles with
`-Werror` in-tree.
