From: Zong-Zhe Yang Originally, TX queue flags was declared by pure unsigned long but was used with bitops, e.g. test_bit. Although for now, there are not much cases in enum rtw89_txq_flags to be over than bits that one long can deal with, it indeed missed logical boundary check. Refine it to be declared by DECLARE_BITMAP(). Resolve ARRAY_VS_SINGLETON (Out-of-bounds access) reported by Coverity. (doesn't change logic) Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/core.c | 24 +++++++++---------- drivers/net/wireless/realtek/rtw89/core.h | 5 +++- drivers/net/wireless/realtek/rtw89/mac80211.c | 4 ++-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 8ab15ee1b155..b074b3677c43 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -4625,7 +4625,7 @@ static void rtw89_core_ba_work(struct work_struct *work) "failed to setup BA session for %pM:%2d: %d\n", sta->addr, tid, ret); if (ret == -EINVAL) - set_bit(RTW89_TXQ_F_BLOCK_BA, &rtwtxq->flags); + set_bit(RTW89_TXQ_F_BLOCK_BA, rtwtxq->flags); } skip_ba_work: list_del_init(&rtwtxq->list); @@ -4658,7 +4658,7 @@ void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); if (sta == txq->sta) { - clear_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags); + clear_bit(RTW89_TXQ_F_FORBID_BA, rtwtxq->flags); list_del_init(&rtwtxq->list); } } @@ -4685,12 +4685,12 @@ static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev, if (unlikely(!rtwsta) || unlikely(rtwsta->disassoc)) return; - if (!test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags) || - test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) + if (!test_bit(RTW89_TXQ_F_AMPDU, rtwtxq->flags) || + test_bit(RTW89_TXQ_F_FORBID_BA, rtwtxq->flags)) return; spin_lock_bh(&rtwdev->ba_lock); - if (!test_and_set_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) + if (!test_and_set_bit(RTW89_TXQ_F_FORBID_BA, rtwtxq->flags)) list_add_tail(&rtwtxq->list, &rtwdev->forbid_ba_list); spin_unlock_bh(&rtwdev->ba_lock); @@ -4709,7 +4709,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta = txq->sta; struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) + if (test_bit(RTW89_TXQ_F_FORBID_BA, rtwtxq->flags)) return; if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) { @@ -4720,10 +4720,10 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, if (unlikely(!sta)) return; - if (unlikely(test_bit(RTW89_TXQ_F_BLOCK_BA, &rtwtxq->flags))) + if (unlikely(test_bit(RTW89_TXQ_F_BLOCK_BA, rtwtxq->flags))) return; - if (test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags)) { + if (test_bit(RTW89_TXQ_F_AMPDU, rtwtxq->flags)) { IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_AMPDU; return; } @@ -4901,7 +4901,7 @@ static void rtw89_forbid_ba_work(struct work_struct *w) spin_lock_bh(&rtwdev->ba_lock); list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->forbid_ba_list, list) { - clear_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags); + clear_bit(RTW89_TXQ_F_FORBID_BA, rtwtxq->flags); list_del_init(&rtwtxq->list); } spin_unlock_bh(&rtwdev->ba_lock); @@ -6036,13 +6036,13 @@ static void _rtw89_core_set_tid_config(struct rtw89_dev *rtwdev, if (mask & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) { if (tid_conf->ampdu == NL80211_TID_CONFIG_ENABLE) { - clear_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags); + clear_bit(RTW89_TXQ_F_FORBID_BA, rtwtxq->flags); } else { - if (test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags)) + if (test_bit(RTW89_TXQ_F_AMPDU, rtwtxq->flags)) ieee80211_stop_tx_ba_session(sta, txq->tid); spin_lock_bh(&rtwdev->ba_lock); list_del_init(&rtwtxq->list); - set_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags); + set_bit(RTW89_TXQ_F_FORBID_BA, rtwtxq->flags); spin_unlock_bh(&rtwdev->ba_lock); } } diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index c300d15581fc..d725124b39bf 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -244,6 +244,8 @@ enum rtw89_txq_flags { RTW89_TXQ_F_AMPDU = 0, RTW89_TXQ_F_BLOCK_BA = 1, RTW89_TXQ_F_FORBID_BA = 2, + + NUM_OF_RTW89_TXQ_FLAGS, }; enum rtw89_net_type { @@ -1313,8 +1315,9 @@ struct rtw89_core_tx_request { struct rtw89_txq { struct list_head list; - unsigned long flags; int wait_cnt; + + DECLARE_BITMAP(flags, NUM_OF_RTW89_TXQ_FLAGS); }; struct rtw89_mac_ax_gnt { diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index c1be69a3c192..cf356a54d91c 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -1043,7 +1043,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_STOP_CONT: case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: - clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags); + clear_bit(RTW89_TXQ_F_AMPDU, rtwtxq->flags); clear_bit(tid, rtwsta->ampdu_map); rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -1051,7 +1051,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, rtw89_phy_ra_recalc_agg_limit(rtwdev); break; case IEEE80211_AMPDU_TX_OPERATIONAL: - set_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags); + set_bit(RTW89_TXQ_F_AMPDU, rtwtxq->flags); rtwsta->ampdu_params[tid].agg_num = params->buf_size; rtwsta->ampdu_params[tid].amsdu = params->amsdu; set_bit(tid, rtwsta->ampdu_map); -- 2.25.1