# DF-1290 — mly_process_event OOB write on mly_btl

## Finding
`mly_process_event` at `sys/dev/raid/mly/mly.c:1323/1347` indexes
`sc->mly_btl[me->channel][me->target]` using controller-event-supplied u8
fields `me->channel` and `me->target`. `mly_btl` is sized
`[MLY_MAX_CHANNELS=6][MLY_MAX_TARGETS=16]` (`mlyreg.h:59-60`). A malicious or
buggy controller can deliver channel=255, target=255 → array offset 4335
elements (~170 KB) past `mly_btl`. The `case 'l'`/`'m'` logical-device path
at `mly.c:1327-1332` computes `bus = MLY_LOGDEV_BUS(sc, me->lun)` which can
also yield `bus >= MLY_MAX_CHANNELS` without any `MLY_BUS_IS_VALID` check.

## Why we did not reproduce at runtime
Same reason as DF-1289: no Mylex HBA on the QEMU/KVM guest. The driver is
compiled into GENERIC but never attaches. `mly_process_event` is reachable
only from the driver's 1-second periodic callout (`mly_check_event`), which
fires only after `mly_attach` succeeds. With no HBA, none of this runs.

## Source-level confirmation
- `mly.c:1323` — `sc->mly_btl[me->channel][me->target].mb_flags |= MLY_BTL_RESCAN;` (no bounds check; `case 'p'`)
- `mly.c:1327` — `bus = MLY_LOGDEV_BUS(sc, me->lun);` (no MLY_BUS_IS_VALID)
- `mly.c:1330` — `mly_printf(... sc->mly_btl[bus][target].mb_name ...)` (indexes unvalidated bus)
- `mly.c:1332` — `sc->mly_btl[bus][target].mb_flags |= MLY_BTL_RESCAN;` (writes unvalidated bus)
- `mly.c:1347` — `sc->mly_btl[me->channel][me->target].mb_flags |= MLY_BTL_RESCAN;` (no bounds; `case 's'`)
- `mlyreg.h:59-60` — `MLY_MAX_CHANNELS 6`, `MLY_MAX_TARGETS 16`
- `mlyvar.h:286` — `MLY_BUS_IS_VALID(sc, bus)` macro exists and is used elsewhere (e.g. `mly.c:803, 825, 1379, 2187`) but **not** in `mly_process_event`.

Compare `mly.c:2187` (`mly_cam_action`) which **does** validate:
`if (!MLY_BUS_IS_VALID(sc, bus)) { ... return; }` — proving the pattern is
established; `mly_process_event` simply omits it. Bug is real.

## Realistic impact ceiling
A hostile/faulty Mylex HBA can drive a ~170 KB OOB **write** (sets the
`MLY_BTL_RESCAN` bit, which is `1<<3`, on attacker-chosen elements of the
softc at attacker-chosen offset). Because the write only sets a single bit,
grooming is constrained, but on a non-debug kernel the corruption of adjacent
softc state is in principle exploitable for DoS at minimum. Threat model is
again "hostile PCI device".

## Fix
`fix.diff` adds explicit `me->channel < MLY_MAX_CHANNELS && me->target < MLY_MAX_TARGETS` checks before the two physical-device writes, and a
`bus >= MLY_MAX_CHANNELS || target >= MLY_MAX_TARGETS` early-out in the
logical-device case.
