# DF-4817 — iwm phy_db: latent heap OOB read in `channel_id_to_txp()` —
entry length never checked before reading `txp_chg->max_channel_idx`

## File
`sys/dev/netif/iwm/if_iwm_phy_db.c` (pass 2, GLM 5.3 re-audit)

## Class
CWE-125 (out-of-bounds read), **latent / currently unreachable in-tree**
(hardening finding, Info severity).

## The defect
`channel_id_to_txp()` (if_iwm_phy_db.c:372-393) walks the TXP channel-group
entries:

```c
for (i = 0; i < phy_db->n_group_txp; i++) {
        txp_chg = (void *)phy_db->calib_ch_group_txp[i].data;
        if (!txp_chg)
                return 0xff;                      /* NULL check only   */
        if (le16toh(txp_chg->max_channel_idx) >= ch_index)   /* OOB read */
                return i;
}
```

It validates only that `data != NULL`, never that
`calib_ch_group_txp[i].size >= sizeof(struct iwm_phy_db_chg_txp)` (6 bytes:
`uint32_t space; uint16_t max_channel_idx;` — if_iwmreg.h:2298-2301, packed).
A firmware that sent a CHG_TXP section with `length` in [0..5] produces a
`kmalloc(size)` entry (kmalloc(0) is a legal allocation in DragonFly —
kern_slaballoc.c handles the degenerate size==0 case and returns a non-NULL
pointer) whose `max_channel_idx` read runs past the allocation by up to 6
bytes. The NULL check passes because the pointer is non-NULL.

## Why it is latent (reachability analysis)
`channel_id_to_txp()` is `static` and has exactly one caller:
`iwm_phy_db_get_section_data()` (if_iwm_phy_db.c:410), invoked when
`type == IWM_PHY_DB_CALIB_CHG_TXP`. `iwm_phy_db_get_section_data()` itself is
`static` with exactly two call sites — if_iwm_phy_db.c:506
(`IWM_PHY_DB_CFG`) and :523 (`IWM_PHY_DB_CALIB_NCH`), both in
`iwm_send_phy_db_data()`. Neither passes a CHG type, so the TXP lookup path
(including this read) is dead code in this tree today. It becomes live the
moment anyone wires `iwm_phy_db_get_section_data()` for channel-group types
(e.g. porting channel-selection flows from newer iwlwifi, where this helper
is used for per-channel TXP retrieval).

## Build / run
No PoC possible: hardware-gated (see DF-4816 pack — guest has no Intel
Wireless device) *and* the buggy path is unreachable in the current tree.
Filed as Info: hardening/latent memory-safety defect with a one-line fix.

## Fix
See `fix.diff` — size-check each entry before reading the header.
