The nxpwifi RX reorder code indexes several MAX_NUM_TID-sized arrays (struct nxpwifi_private::rx_reorder_tbl_ptr[8] and rx_reorder_tbl_lock[8], main.h:548/550) with a tid that is neither validated at the callers nor at the function entry, and accesses a win_size-sized flex array (tbl->rx_reorder_ptr[]) with a pkt_index that can exceed win_size. Both are remote-reachable through a received 802.11 frame. Bug 1 - tid used as array index without bounds check nxpwifi_11n_rx_reorder_pkt() and nxpwifi_11n_create_rx_reorder_tbl() take a tid parameter that flows directly into: list_for_each_entry_rcu(tbl, &priv->rx_reorder_tbl_ptr[tid], list) (11n_rxreorder.c:187) spin_lock_bh(&priv->rx_reorder_tbl_lock[tid]); (11n_rxreorder.c:324) list_add_tail_rcu(&new_node->list, &priv->rx_reorder_tbl_ptr[tid]); (11n_rxreorder.c:325) These arrays have MAX_NUM_TID (8) entries. The tid comes from local_rx_pd->priority in the receive path (sta_rx.c:232, uap_txrx.c:405) - a u8 filled by firmware from the received frame's rxpd, range 0-255 - or from the 4-bit TID field of an ADDBA request (11n_rxreorder.c:379, range 0-15). Neither path checks tid < MAX_NUM_TID before calling into the reorder code; sta_rx.c:224-226 does gate the rx_seq[] write on priority < MAX_NUM_TID, but the subsequent nxpwifi_11n_rx_reorder_pkt() call at sta_rx.c:232 drops the same check. A tid >= 8 reads rx_reorder_tbl_ptr[] out of bounds, takes a spinlock on a garbage address, and writes an out-of-bounds list_head. Fix: validate tid < MAX_NUM_TID at the entry of both nxpwifi_11n_rx_reorder_pkt() and nxpwifi_11n_create_rx_reorder_tbl(), covering all callers. Bug 2 - pkt_index not bounded by win_size tbl->rx_reorder_ptr is allocated with win_size entries (11n_rxreorder.c:280, kzalloc_flex). In nxpwifi_11n_rx_reorder_pkt() the out-of-window drop check (11n_rxreorder.c:459-470) uses TWOPOW11 (2048) rather than win_size, so a seq_num within [start_win, start_win + 2048) passes the drop check regardless of win_size. pkt_index is then computed as seq_num - start_win (11n_rxreorder.c:491) and can reach 0..2047, but the write tbl->rx_reorder_ptr[pkt_index] = payload; (11n_rxreorder.c:500) only has win_size slots. With win_size = 1 (allowed: create_rx_reorder_tbl only rejects win_size <= 0 at 11n_rxreorder.c:276) any pkt_index > 0 is a heap out-of-bounds write of up to ~2048 pointer slots. Fix: bound pkt_index against tbl->win_size before the rx_reorder_ptr[] access. Together these close an out-of-bounds read + spinlock-on-garbage and an out-of-bounds heap write, both reachable from a received frame. Fixes: 73b01e57ed3e ("wifi: nxp: add nxpwifi driver for IW61x") Cc: stable@vger.kernel.org Signed-off-by: guohongyu --- drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c b/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c index 87cf2ec85991..111225594144 100644 --- a/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c +++ b/drivers/net/wireless/nxp/nxpwifi/11n_rxreorder.c @@ -266,6 +266,9 @@ nxpwifi_11n_create_rx_reorder_tbl(struct nxpwifi_private *priv, u8 *ta, u16 last_seq = 0; struct nxpwifi_sta_node *node; + if (tid >= MAX_NUM_TID) + return; + /* Existing TID/TA: flush and move window to SSN. */ tbl = nxpwifi_11n_get_rx_reorder_tbl(priv, tid, ta); if (tbl) { @@ -421,6 +424,9 @@ int nxpwifi_11n_rx_reorder_pkt(struct nxpwifi_private *priv, bool init_window_shift = false; int ret = 0; + if (tid >= MAX_NUM_TID) + return -EINVAL; + tbl = nxpwifi_11n_get_rx_reorder_tbl(priv, tid, ta); if (!tbl) { if (pkt_type != PKT_TYPE_BAR) @@ -492,6 +498,11 @@ int nxpwifi_11n_rx_reorder_pkt(struct nxpwifi_private *priv, else pkt_index = (seq_num + MAX_TID_VALUE) - start_win; + if (pkt_index >= tbl->win_size) { + ret = -EINVAL; + goto done; + } + if (tbl->rx_reorder_ptr[pkt_index]) { ret = -EINVAL; goto done; -- 2.43.0