# DF-4330 — VERDICT

**Status: reproduced (certain). Impact demonstrated: deterministic OOB kernel
write past the softc allocation with firmware-controlled byte values.**

## Root cause (code trace)

1. The RAID map is DMA'd from the adapter into `sc->raidmap_mem[]`
   (`mrsas.c:3135-3174`, `MR_DCMD_LD_MAP_GET_INFO`), `map_sz =
   sizeof(MR_FW_RAID_MAP) + sizeof(MR_LD_SPAN_MAP)*63` (`mrsas.c:1645-1646`).
2. `MR_ValidateMapInfo` (`mrsas_fp.c:247-274`) validates **only**
   `pFwRaidMap->totalSize` against a `ldCount`-derived size (`:257-265`). No
   per-LD geometry is validated.
3. When fw advertises `supportUnevenSpans` (`mrsas.c:1757-1762`, also re-run at
   every AEN map update `mrsas.c:2961`), `MR_ValidateMapInfo` calls
   `mr_update_span_set` (`:267-268`).
4. `mr_update_span_set` (`:916-1021`) iterates `span < raid->spanDepth`
   (fw `u_int8_t`, 0..255) over `spanBlock[MAX_RAIDMAP_SPAN_DEPTH = 8]`
   (OOB reads — DF-1528 class) and, for each element, runs
   `for (count = 0; count < raid->spanDepth; count++) ... span_set->strip_offset[count]
   = span_row_width;` (`:949-959`) — **`strip_offset` is `u_int8_t[8]`
   (`mrsas.h:733`)**. With `spanDepth = 64..255` this writes up to 247 bytes
   past each `LD_SPAN_SET` (88 bytes each), cascading through
   `ldSpanInfo[ld].span_set[0..7]` and, for `ld = 63`, **past the end of
   `sc->log_to_span[MAX_LOGICAL_DRIVES]` — the last member of
   `struct mrsas_softc` (`mrsas.h:2423-2425`)** — into whatever kernel memory
   follows the softc allocation.
5. Written values: `span_row_width` accumulates fw-chosen
   `spanRowDataSize` (`u_int8_t`) per qualifying span
   (`:958`), so the overflow content is fw-chosen bytes (PoC shows exact
   running-sum values 0x00..0x3f at guard offsets +0..+39).

## Reproduction (guest, unmodified driver source)

Probe KLD `fp_probe.ko` compiles the guest's own `/usr/src/sys/dev/raid/mrsas/
mrsas_fp.c` (symbol-renamed, zero source edits) and calls the real
`MR_ValidateMapInfo()` with a fw-shaped map (`spanDepth=64`, consistent
`totalSize`) against a real `struct mrsas_softc` followed by a 0xAA guard.

Result (`run.log`, reproduced across 3 independent runs/boot cycles):

```
fp_probe: MR_ValidateMapInfo returned 0 (0 == map accepted, spansets built)
fp_probe: *** DF-4330 CONFIRMED: OOB WRITE past end of sc->log_to_span[64]
          (last softc member): first clobbered byte at +0 = 0x18
...
fp_probe: guard integrity: 40/4096 bytes clobbered past softc end
```

Baseline behavior: the **current** validation accepts the malicious map
(returns 0) and the write happens; guard bytes +0..+39 hold the exact
accumulated widths (0x18,0x19,...,0x3f with this map shape). LD 63 /
element 7 / count 8..63 arithmetic: offset into `ldSpanInfo[63]` =
`7*88 + 64 + count` = 680..743 vs array size 704 → 39-40 bytes past the
64-entry array, i.e. past the softc tail.

## Exploit chain

Not pushed to `uid=0`: the write source is DMA'd firmware data and no mrsas
HBA exists in the QEMU guest, so in-situ heap shaping cannot be demonstrated.
Primitive as proven: a linear, firmware-authored overflow of up to ~230 bytes
past `sc->log_to_span[]` into adjacent kernel heap (the softc is the driver's
root object; on real hardware whatever follows it in the kmalloc/device zone
gets fw-chosen bytes), plus mass corruption of the `log_to_span` interior
itself (span_set geometry fields), which feeds later divisions and index walks.
Classification: kernel memory corruption (bucket memcorrupt); realistic impact
ceiling DoS→controlled corruption under a compromised firmware/PCIe device.

## Fix validation

`fix.diff` adds per-LD geometry validation to `MR_ValidateMapInfo` (spanDepth ≤
`MAX_RAIDMAP_SPAN_DEPTH` and != 0, noElements ≤ `MAX_QUAD_DEPTH`, every live
quad `diff != 0`, `spanRowSize != 0` for RAID 0/5/6) before any spanset build.
Validated by compiling the patched `mrsas_fp.c` into the same probe (same
kernel build flags, same call path — the file is compiled into the kernel
either way):

* baseline (unpatched): map accepted, 40/4096 guard bytes clobbered
  (`run.log`)
* patched: mode 0 benign map still **accepted** (`fix_run.log`:
  "returned 0", "sanity OK", guard 0/4096) — no valid-map regression;
* patched: mode 1 malicious map **rejected** ("nexus0: invalid RAID map
  geometry (ld/span/quad), rejecting map", returned 1, guard 0/4096);
* patched: mode 2 (diff=0, DF-4331 input) also **rejected** — no panic.

Module-level validation was used instead of a full kernel rebuild: the
compiled unit, flags and entry function are identical to the in-kernel build
(mrsas is `device mrsas` in X86_64_GENERIC); a whole-kernel rebuild adds no
additional coverage of this file's code path.

## Artifacts

* `fp_probe.c`, `rename.h`, `Makefile`, `build.sh` — probe
* `run.log` — baseline (unpatched): sanity + OOB write
* `fix_run.log` — patched: benign accepted, malicious rejected twice
* `build.log` / `fix_build.log` — full untrimmed builds of both variants
* `serial_decisive.log` — serial-console record incl. DF-4331 panic
* `fix.diff` — git-apply-able (`git apply --check` passes vs this tree)

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