The TID field in IEEE 802.11 Block Ack parameter sets is a 4-bit field (bits 2-5 of IEEE80211_ADDBA_PARAM_TID_MASK = 0x003C), yielding values 0-15 when extracted. However, mwifiex only supports 8 TIDs (MAX_NUM_TID = 8), and uses TID values to index the aggr_prio_tbl array. A malicious USB device (or a crafted firmware response) can supply an AddBA response with TID >= 8, causing out-of-bounds array accesses in: - mwifiex_ret_11n_addba_req(): OOB write to aggr_prio_tbl[tid].ampdu_ap and OOB read of aggr_prio_tbl[tid].amsdu - mwifiex_cmd_11n_addba_rsp_gen(): OOB read of aggr_prio_tbl[tid].amsdu - mwifiex_ret_11n_addba_resp(): OOB read of aggr_prio_tbl[tid].amsdu Add bounds checks against MAX_NUM_TID immediately after extracting the TID value from the block ack parameter set in all three functions. Fixes: 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex driver") Signed-off-by: Aamir Ahmed --- drivers/net/wireless/marvell/mwifiex/11n.c | 2 ++ drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c index cef8a55427dd..82b1d35926c1 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n.c +++ b/drivers/net/wireless/marvell/mwifiex/11n.c @@ -153,6 +153,8 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) >> BLOCKACKPARAM_TID_POS; + if (tid >= MAX_NUM_TID) + return -1; tid_down = mwifiex_wmm_downgrade_tid(priv, tid); ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, add_ba_rsp-> diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index 9deb47f22a61..80fafe08b6dc 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -492,6 +492,8 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, block_ack_param_set = le16_to_cpu(cmd_addba_req->block_ack_param_set); tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) >> BLOCKACKPARAM_TID_POS; + if (tid >= MAX_NUM_TID) + return -1; add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; @@ -721,6 +723,8 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) >> BLOCKACKPARAM_TID_POS; + if (tid >= MAX_NUM_TID) + return -1; /* * Check if we had rejected the ADDBA, if yes then do not create * the stream -- 2.43.0