# DF-4093 VERDICT

**Status:** not_reproduced (kernel level) — hardware-gated; **primitive proven
at object level on the audit guest** (userland harness, verbatim range
function, walks and both write sinks). **Confidence:** certain.

mpr twin of DF-4086 (mps). Filed separately because the mps pass-2 audit
deliberately did not double-file sibling findings.

## Source chain (line-by-line)

1. `mpr_mapping.c:2564-2565` `max_volumes = facts->MaxVolumes` (u8),
   `max_devices = facts->MaxTargets + facts->MaxVolumes`.
2. `mpr_mapping.c:2140-2141` `mapping_table = kmalloc(32 * max_devices)`
   (sizeof verified 32 on amd64, mprvar.h:113-125).
3. `mpr_mapping.c:241-255` `_mapping_get_ir_maprange`: with
   `IRVolumeMappingFlags == LOW_VOLUME_MAPPING` (:246-248) `start_idx = 0`,
   bumped to 1 when `MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0` (:250-251);
   `*end_idx = *start_idx + sc->max_volumes - 1` (:254) — **unclamped**.
   With firmware facts `MaxTargets == 0` (⇒ `max_devices == max_volumes`),
   `RESERVED_TARGETID_0` and low volume mapping — all three firmware-
   controlled — `start_idx = 1` and `end_idx = max_volumes = max_devices`:
   one entry PAST the last valid index.
4. Every IR consumer walks `map_idx <= end_idx` and therefore touches
   `mapping_table[max_devices]`:
   - `_mapping_get_ir_mt_idx_from_wwid`   **:387**  OOB read (physical_id)
   - `_mapping_get_ir_mt_idx_from_handle` **:430**  OOB read (dev_handle)
   - `_mapping_get_free_ir_mt_idx`        **:484**  OOB read (device_info/
     missing_count) and **:486 returns the OOB index** when the adjacent
     memory lacks `MPR_MAP_IN_USE`
   - `_mapping_process_dpm_pg0` volume branch **:2260-2271** accepts
     `dev_idx == end_idx` (DPM pg0 `DeviceIndex`, u16, fw-controlled) and
     writes a full entry at `mapping_table[dev_idx]` — **unconditional
     32-byte OOB write** with fw `PhysicalIdentifier`
   - `mpr_mapping_get_raid_tid`           **:2708** OOB read (CAM-facing
     volume lookup)
5. Write sink A (event): `mpr_mapping_ir_config_change_event` **:3045-3088**
   — on `MPI2_EVENT_IR_CHANGE_RC_ADDED`/`VOLUME_CREATED` for a volume whose
   WWID is not yet mapped, `map_idx = _mapping_get_free_ir_mt_idx(sc)`
   (:3071) returns `max_devices` when the in-range slots are busy;
   **:3082-3088** writes `physical_id = wwid_table[i]` (fw volume WWID),
   `id`, `dev_handle`, `device_info` — full 32-byte fw-controlled entry one
   past the allocation.
   Write sink B (boot): the :2260-2271 DPM volume-branch write above — same
   index, reached at attach time from persistent mapping entries.

Note: `_mapping_get_high_missing_mt_idx` (:341-370) computes
`&mapping_table[end_idx_ir + 1]` == `&mapping_table[max_devices + 1]` in the
same configuration (:358) but its `<` loop then never dereferences it —
benign pointer arithmetic, noted for completeness.

### Distinct from the existing mpr findings

None of DF-3914..DF-3919 touches `_mapping_get_ir_maprange` or the IR walks;
DF-3919 covers event *element-count* walks (frame-length mismatch), not the
IR index range.

## Verification performed

- Guest `pciconf -l` (env.txt): no SAS HBA ⇒ `mpr_attach` never runs;
  kernel-level reproduction impossible (same gate as DF-3914/DF-3915/
  DF-4086).
- `harness_df4093.c` built and run **twice** as the unprivileged user on the
  guest (cc 8.3, zero warnings): verbatim range function (:241-255 low+reserved
  configuration), verbatim `<=` walks, verbatim event write (:3082-3088) and
  verbatim DPM volume branch (:2260-2271). Facts MaxTargets=0, MaxVolumes=255
  ⇒ max_devices=255, start=1, **end=255 == max_devices**. Decisive results
  (run.log, stable):
  - wwid walk reads `physical_id` at `mapping_table[255]` — OOB read;
  - free-idx walk **returns 255** (== max_devices) — the OOB index escapes;
  - event write lands the fw WWID `0x57119418BADB00B5` at guard[255] —
    32-byte heap OOB write, verified programmatically;
  - DPM volume branch accepts `DeviceIndex 255 == end_idx` — a second,
    unconditional 32-byte OOB write.
- In-kernel equivalent: one 32-byte struct write just past an 8,160-byte
  kmalloc, contents firmware-chosen (volume WWID at offset 0, dev_handle,
  device_info). On the no-hardening audit guest this is classic adjacent-
  slab-object corruption once an HBA is present.

## Fix validation

- `fix.diff` (this pack): clamp `*end_idx` to `sc->max_devices - 1` at the
  end of `_mapping_get_ir_maprange` — same shape as the validated DF-4086
  fix; fixes every `<=` consumer at once (:387, :430, :484, :2261, :2708).
- Applied together with DF-4092's bound-skip to the guest `/usr/src`;
  `make` in `sys/dev/raid/mpr` compiled all sources with `-Werror` and
  linked **mpr.ko** (BUILD_EXIT=0) — `fix_build.log`.
- Runtime fix validation not testable (no mpr HBA on the guest).
- `/usr/src` restored pristine after the build (md5 match, reverse-patch
  verified, no leftover artifacts).

## Bottom line

Source-certain CWE-125/ CWE-787 off-by-one → OOB reads + two distinct
32-byte OOB write sinks, primitive proven at object level on the audit
guest; kernel-level reproduction hardware-gated. Fix compiles clean with
-Werror; recommended for upstream together with the mps twin DF-4086.

## 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.
