# DF-1243 — mrsas_get_pd_list unchecked deviceId (OOB write into softc)

## Verdict: NOT REPRODUCED (dead code at runtime — no hardware)

## Mechanism (source-level, confirmed real)

`mrsas_get_pd_list()` at `sys/dev/raid/mrsas/mrsas.c:3270` queries the
firmware for the physical-drive list and populates
`sc->local_pd_list[deviceId]`. The deviceId is firmware-supplied and
**unchecked** against the array bounds:

```c
// line 3307-3314
if (retcode == 0 && pd_list_mem->count < pd_count) {   // checks count, NOT deviceId
    memset(sc->local_pd_list, 0, MRSAS_MAX_PD * sizeof(struct mrsas_pd_list));
    for (pd_index = 0; pd_index < pd_list_mem->count; pd_index++) {
        sc->local_pd_list[pd_addr->deviceId].tid = pd_addr->deviceId;
        sc->local_pd_list[pd_addr->deviceId].driveType = pd_addr->scsiDevType;
        sc->local_pd_list[pd_addr->deviceId].driveState = MR_PD_STATE_SYSTEM;
        pd_addr++;
    }
}
```

`deviceId` is `u_int16_t` (0–65535, mrsas.h:1351), but `local_pd_list`
has only **`MRSAS_MAX_PD = 256`** entries (mrsas.h:2417, 1830). The guard
at line 3307 only bounds the **count** (< 256), not the **deviceId** values.

The softc layout after `local_pd_list[256]` (mrsas.h:2417-2424):
```
struct mrsas_pd_list local_pd_list[256];   // <-- the array
u_int8_t          ld_ids[MRSAS_MAX_LD];    // overwritten
struct taskqueue  *ev_tq;                  // <-- KERNEL FUNCTION POINTER
struct task       ev_task;
u_int32_t         CurLdCount;
u_int64_t         reset_flags;
LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
```

A `deviceId >= 256` writes `.tid`, `.driveType`, `.driveState` (3 fields of
a `struct mrsas_pd_list`) past the array into `ld_ids`, and for large
deviceId values, potentially into `ev_tq` — a **kernel taskqueue
pointer**. Corrupting a function pointer and triggering the event task
could redirect kernel execution.

**The bug is real in source.** A malicious firmware can set `deviceId` to
any u16 value, causing an OOB write of 3 fields per entry past the
256-entry array, corrupting adjacent softc fields including a taskqueue
pointer. Triggered at attach and re-triggered on PD_INSERTION events.

## Why it cannot reproduce on this guest

Same as DF-1242: `mrsas` **is in GENERIC** but **no LSI MegaRAID SAS
hardware** on the QEMU guest → driver never attaches →
`mrsas_get_pd_list` (called from `mrsas_init_adapter` during attach) is
never reached.

**Valid hard blocker: dead/unreachable at runtime.** Threat model is
malicious firmware or a malicious PCIe device on a real MegaRAID SAS
system.

## Fix

`fix.diff` adds `if (pd_addr->deviceId >= MRSAS_MAX_PD) { skip; continue; }`
inside the loop, so out-of-range deviceIds are logged and skipped rather
than writing OOB. Validated by a successful single-fix kernel build
(`make -j6 nativekernel` rc=0).

## Impact

- **On this guest**: none (driver never attaches, no hardware).
- **On a real system**: OOB write of 3 fields per malicious PD entry past
  `local_pd_list[256]`, corrupting `ld_ids`, `ev_tq` (taskqueue pointer),
  `reset_flags`, `load_balance_info`. From malicious firmware this is
  kernel memory corruption in the RAID driver — a crash (DoS) from buggy
  firmware, or a controlled corruption primitive (including potential
  function-pointer overwrite of `ev_tq`) from a malicious PCIe device.
  Triggered at attach and on PD events.
