# DF-1279 — Divide-by-zero in mpt_configure_ioc (RequestFrameSize == 0)

## Finding
In `mpt_configure_ioc` (`sys/dev/disk/mpt/mpt.c:2623`), after `mpt_get_iocfacts`
fills in `mpt->ioc_facts` (line 2650-2654), the driver computes its segment
limits at line 2683:

```c
mpt->max_seg_cnt *= MPT_NRFM(mpt);
```

where, from `mpt.h:882`:

```c
#define MPT_NRFM(mpt)        (MPT_REQUEST_AREA / MPT_RQSL(mpt))
#define MPT_RQSL(mpt)        (mpt->ioc_facts.RequestFrameSize << 2)
```

If a malicious or buggy IOC returns `IOCFACTS.RequestFrameSize == 0`, then
`MPT_RQSL(mpt) == 0` and the macro divides `MPT_REQUEST_AREA` (512) by zero.
The kernel takes a `#DE` (divide-by-zero) trap and panics. There is no
validation between the facts fetch (line 2654) and the use as a divisor
(line 2683).

## Fix
Insert a guard immediately after `mpt2host_iocfacts_reply` (line 2654): if
`RequestFrameSize == 0`, log and return `EINVAL`. Real IOC firmware always
reports a non-zero frame size; the guard only ever fires on a broken or
malicious device.

## Verification on this guest
- The mpt driver is in `X86_64_GENERIC`, but no MPT HBA is present in the
  QEMU guest (see DF-1278 README for PCI listing), so `mpt_configure_ioc`
  never executes. Bug is **not runtime-triggerable on this guest**.
- Source-level confirmation:
  - `mpt.h:876` — `MPT_RQSL(mpt) = mpt->ioc_facts.RequestFrameSize << 2`.
  - `mpt.h:882` — `MPT_NRFM(mpt) = MPT_REQUEST_AREA / MPT_RQSL(mpt)`.
  - `mpt.c:2683` — `mpt->max_seg_cnt *= MPT_NRFM(mpt);` is the divide sink.
  - `mpt.c:2654` — facts retrieved; no validation between this and line 2683.
- Fix verified to compile (combined build with DF-1278/1280/1285/1287).

## Realistic impact ceiling
Hardware-attacker (PCIe/Thunderbolt/external chassis) DoS: `#DE` kernel panic
at attach/hot-plug. Same threat model as DF-1278.
