# VERDICT — DF-1449: mpt_raid.c unvalidated firmware indices → OOB read/write of RAID arrays

## Verdict

**INCONCLUSIVE (HW/module gated) — source-level confirmed, fix validated.**

The bug is real and present in master DEV source at `sys/dev/disk/mpt/mpt_raid.c:414, 1155, 1309, 1405, 1436`,
but the affected driver attaches only to hardware not present in the audit QEMU
guest, so it cannot be live-triggered here. The fix.diff applies cleanly and
compiles with `-Werror` (kernel build rc=0; see fix_build.log).

## Mechanism (cited path → primitive → effect)

`raid_disks[]` and `raid_volumes[]` are kmalloc'd with `ioc_page2->MaxPhysDisks` / `MaxVolumes` entries (mpt.c:2019,1990). Firmware-supplied indices index them with NO bounds check: raid_event->PhysDiskNum at mpt_raid.c:414; vol_pg->PhysDisk[i].PhysDiskNum at 1155/1309; ioc_disk->PhysDiskNum at 1405; ioc_vol->VolumePageNumber at 1436. A malicious HBA returning PhysDiskNum/VolumePageNumber >= MaxPhysDisks/MaxVolumes corrupts adjacent slab memory. The for-loops bounded by NumPhysDisks/NumActiveVolumes iterate based on firmware counts without validation against the allocation.

## Reachability on this guest

No — mpt(4) is in GENERIC but requires an LSI Fusion HBA. No HW in the audit guest; trigger is a malicious/faulty HBA sending crafted IOC pages or RAID events.

## Phase 6 — escalation potential

This is a heap-OOB (firmware-controlled indices) primitive. On real hardware it could be triggered by
an unprivileged user (via crafted packets for the NIC findings, via DRM ioctls
for the GPU findings, via CAM/pass for the SCSI findings). On **this guest**
there is no live primitive to convert. Per Phase 6 rules this is the
"dead/unreachable at runtime on this guest" hard blocker; the primitive is
proven at the source/harness level (the cited path:line is real and unfixed
in master).

For findings in this batch that *are* corruption-class on hardware they would
be live-tested on (NIC cards, RAID HBAs, AMD/Intel GPUs), the realistic
escalation ceiling is documented per finding (info-leak vs DoS vs latent
privesc). No `uid=0` claim is made — none is reachable on this guest.

## Phase 8 — fix validation

`fix.diff` is a minimal, targeted fix at the root cause confirmed above.

- **Applied cleanly** with `patch -p1 --forward` (verified in `fix_apply.log`).
- **Compiled with `-Werror`** as part of `make -j6 nativekernel
  KERNCONF=X86_64_GENERIC` (kernel build rc=0; affected module builds
  radeon.ko/amdgpu.ko/sound.ko/i915.ko/vga_switcheroo.ko all produced).
- For musycc.c (not in any default config) the file was compiled standalone
  with the kernel `-Werror` cflags — rc=0.

Add `PhysDiskNum < raid_max_disks` / `VolumePageNumber < raid_max_volumes` bounds checks at each of the 5 OOB sites; skip-and-log on out-of-range.

## PoC changes

Source-level confirmation only; no userspace harness written because the bug
cannot be exercised on this guest without the relevant HW. The placeholder
`build.sh`/`run.sh` echo pointers to `VERDICT.md` and the module/kernel
rebuild path.
