# DF-1283 — OOB heap write via unsigned underflow / missing bounds check in slot arithmetic (`_mapping_add_new_device` / `_mapping_add_new_pcie_device`)

**File:** `sys/dev/raid/mpr/mpr_mapping.c:1637` (SAS), `:1894` (PCIe)
**Class:** CWE-787 Out-of-bounds Write (heap) + unsigned integer underflow
**Severity:** High

## The bug (source-confirmed)

In `_mapping_add_new_device` (and the PCIe twin `_mapping_add_new_pcie_device`),
the mapping-table index for a newly added device is computed at `:1637`:

```c
map_idx = et_entry->start_index + phy_change->slot - et_entry->start_slot;
mt_entry = &sc->mapping_table[map_idx];            /* :1639, unguarded */
```

Types (verified): `map_idx` is `u32` (`:1579`), `phy_change->slot` is `uint16_t`
(`mpr_mapping.h:48`), `et_entry->start_slot` is `u16` (`mprvar.h:148`),
`et_entry->start_index` is `u32` (`mprvar.h:143`). `mapping_table` is allocated
for `max_devices` entries (`:2140`).

There is **no** check that `slot >= start_slot`, and **no** check that
`map_idx < max_devices`. Both `slot` (SAS/PCIe Device Page 0) and `start_slot`
(Enclosure Status Change event) are firmware-controlled `u16` values. Two failure
modes result:

- **slot too large:** `start_index + slot - start_slot >= max_devices` → straight
  OOB heap write past the allocation.
- **underflow:** `slot < start_slot` → `(start_index + slot) - start_slot` wraps
  to a huge `u32` (e.g. `0xFFFFFFFB`) → wild out-of-slab pointer dereference.

## Reachability / threat model

Same as DF-1282: the `mpr` driver is hardware-bound (LSI/Avago SAS HBA), **not
present** in the audit QEMU guest, so not runtime-reachable here. The path runs
on SAS/PCIe topology-change events, so a malicious peripheral / expander /
firmware supplying a crafted slot or enclosure start_slot triggers it on real
hardware. See `VERDICT.md`.

## Reproduce (harness)

```sh
./build.sh && ./run.sh
```

Decisive output:
```
Case A: map_idx=310 >= max_devices=264 -> write at mapping_table[310]   (OOB, adjacent slab)
Case B: map_idx=4294967291 (0xfffffffb) -- WILD POINTER (underflow)
```

## Fix

`fix.diff` adds `slot < start_slot || map_idx >= sc->max_devices` guards to both
the SAS and PCIe paths (continue on violation). Validated: applies cleanly and
the `mpr` module compiles with `-Werror` in-tree.
