# DF-3630 — iwm_handle_rxb: unconditional PAGE_SIZE copy of command responses reads past the 4KB RX cluster

## Where
`sys/dev/netif/iwm/if_iwm.c:5509-5515` (NVM_ACCESS/MCC_UPDATE response path)
and `:5572-5577` (long-command response path) inside `iwm_handle_rxb()`;
consumer `iwm_send_cmd()`/`iwm_free_resp()` at
`sys/dev/netif/iwm/if_iwm_util.c:327,369`.

## What
```c
uint32_t maxoff = IWM_RBUF_SIZE;                 /* 4096 (if_iwmvar.h:290) */
#define HAVEROOM(a) ((a) + sizeof(uint32_t) + sizeof(struct iwm_cmd_header) < maxoff)
while (HAVEROOM(offset)) {                       /* offset can be up to 4087 */
        struct iwm_rx_packet *pkt = mtodoff(m, ..., offset);
        ...
        case IWM_NVM_ACCESS_CMD:
        case IWM_MCC_UPDATE_CMD:
                if (sc->sc_wantresp == (((qid & ~0x80) << 16) | idx)) {
                        memcpy(sc->sc_cmd_resp,
                            pkt, sizeof(sc->sc_cmd_resp));   /* PAGE_SIZE == 4096 ! */
                }
```
`sc_cmd_resp` is `uint8_t sc_cmd_resp[IWM_CMD_RESP_MAX]` with
`IWM_CMD_RESP_MAX = PAGE_SIZE` (`if_iwmvar.h:312,500`). The copy length is
therefore **4096 bytes regardless of the actual firmware packet length or its
offset inside the RX mbuf**. The mbuf is a single `IWM_RBUF_SIZE` (4096-byte)
cluster (`iwm_rx_addbuf`, `if_iwm.c:3044-3055`). A response packet that does
not start at offset 0 — entirely normal, since the firmware may prepend other
notifications to the same receive buffer, and `iwm_handle_rxb` explicitly
walks multiple packets per buffer — makes the copy run up to `offset` bytes
past the end of the cluster (offset max 4087 → up to ~4KB heap OOB read).

The copied bytes are then served to synchronous command consumers as
`cmd->resp_pkt` (`if_iwm_util.c:327`) and parsed, e.g. NVM chunk parsing
reads `nvm_resp->length`/`data` from it. Data does not go directly to
userspace, but the OOB heap read is real kernel-memory disclosure into
driver state (and crash potential when the cluster ends at an unmapped
boundary).

Same class, same fix pattern: `iwm_alive_fn()` (`if_iwm.c:2768-2789`) —
the notification-wait callback receives the *raw* packet
(`iwm_notification_wait_notify(...)` at `:5407`) and its legacy-v3 fallback
branch (`:2784-2789`) reads `palive3` fields with no
`iwm_rx_packet_payload_len()` minimum check (the v4 branch only checks
`== sizeof(*palive)`), an OOB read when the firmware emits a truncated ALIVE.

Not covered by DF-1145: that finding covers MPDU `byte_count`/`mpdu_len`,
`iwm_rx_rx_phy_cmd` and `iwm_handle_rx_statistics` — not the `sc_cmd_resp`
copies nor `iwm_alive_fn`.

## Threat model
Malicious/errant firmware DMA content (same trust boundary as DF-1145, which
was rated High). Multi-notification RX buffers are a normal firmware
behavior, so even *non*-malicious short responses placed after another
notification trigger the overread.

## Reproduce
Kernel path needs iwm hardware (absent on guest — see env.txt). Arithmetic:
copy spans `[m_data+offset, m_data+offset+4096)` while the cluster is
`[m_data, m_data+4096)`; overrun == offset bytes.

## Fix
`fix.diff` — clamp the copy to the actual packet length (`len`, already
computed at `:5403-5404`) capped by `sizeof(sc->sc_cmd_resp)`, and require a
minimum payload length in the `iwm_alive_fn` v3 fallback.
