# DF-3915 — VERDICT

**Status:** not_reproduced (kernel path hardware-gated on this guest) /
wild-read primitive proven at object level.
**Confidence:** certain (source-level; the sink has no bound).

## Verification narrative

1. **Ingestion path** (`sys/dev/raid/mpr/mpr_mapping.c`):
   - `:2251` `dev_idx = le16toh(dpm_entry->DeviceIndex);` (u16 from the
     controller's persistent DPM page read at `mpr_mapping_initialize`
     `:2614`).
   - `:2293-2295` `num_slots` = 7-bit slot field (`0x07F0 >> 4`) — zero is a
     legal, reachable value (an entry that only ever carried missing-count
     bits).
   - `:2310-2311` `start_index = dev_idx`, `dpm_entry_num = entry_num` — both
     stored without any table-size validation.
   - `:2328-2347` reservation loop: with `num_slots == 0` the body never runs,
     so **DF-1282's OOB write is not triggered** — this is what makes the
     corrupt state observable later instead of panicking at boot. (With
     `num_slots >= 1` and `dev_idx >= max_devices`, DF-1282 fires first and
     that state is *its* finding; `num_slots == 0` is the new, distinct
     window.)
2. **Trigger path**: `mpr_mapping_check_devices()` `:2481-2493` — the only
   caller of `_mapping_commit_enc_entry()` in the file (verified by grep).
   Entry requirements met by the ingested state: `init_complete == 0` (never
   set in `_mapping_process_dpm_pg0`), `dpm_entry_num != BAD` (`:2489`).
   Walk-level precondition: at least one enclosure entry with
   `init_complete == 1` so `stop_device_checks` is set (`:2438-2446`) — any
   enclosure that arrived via an Enclosure Status Change event satisfies it
   (`:2847`). `MPR_MISSING_CHECK_DELAY` schedules the callout after discovery.
3. **Sink**: `:129` `mt_entry = &sc->mapping_table[et_entry->start_index];`
   `:130` reads `mt_entry->id` → `dpm_entry->DeviceIndex` (persisted via the
   DPM write path `:142-143`). With `start_index` up to `0xFFFF` the read is
   up to ~2 MB past a ~8 KB allocation: wild pointer.
4. **Hardware gate**: guest `pciconf -l` (env.txt) — virtio-only PCI bus, no
   vendor-0x1000 SAS controller; `mpr_attach()` never runs. Same gate as
   DF-1282/DF-3800 (both previously proven).
5. **Object-level proof** (guest, `run.log`, stable across reruns):
   - the `:2328` loop runs **0** iterations for the crafted entry — the
     DF-1282 bypass is demonstrated, not assumed;
   - the `:129` indexing resolves to +2,096,640 bytes past the 8,448-byte
     table; the harness read returns silent garbage (`0x5f36`) — in the
     kernel this either faults (panic) or persists garbage to NVRAM.
   The harness also installs a `PROT_NONE` guard-page variant (SIGSEGV
   handler) to show the access is genuinely wild when the offset lands on an
   unmapped page.

## Why Medium and not High

Read-only primitive; the corrupted value's destination is the controller's
NVRAM `DeviceIndex` (fed back into driver state), not a userspace info leak.
Primary impact: kernel panic (DoS) from malformed persistent mapping state —
same threat actor as DF-1282 (malicious IOC firmware / NVRAM corruption /
malicious enclosure persisting mapping entries), but strictly weaker than the
write primitives already filed for this file.

## Fix validation

`fix.diff`: reject `start_index == MPR_MAPTABLE_BAD_IDX ||
start_index >= sc->max_devices` at the top of `_mapping_commit_enc_entry`
(before the `:129` deref), log, return -1.
- Applied to the guest `/usr/src` copy together with DF-3914's diff (both
  `git apply --check` clean on the pristine tree).
- `make nativekernel`: `mpr_mapping.c` compiled with `-Werror` in both
  passes (`fix_build.log`).
- `fix_status: not_testable` for runtime: exercising the fixed path needs the
  HBA to serve a malformed DPM page.

## Bottom line

Source-certain wild OOB read (CWE-125) reachable through a DPM-ingested
enclosure entry whose slot count is zero — a state DF-1282 cannot cover
because its own write loop never runs for it. Primitive proven at object
level; kernel path hardware-gated; guard-clause fix compiles clean.

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