From: Yuqi Xu minstrel_ht_tx_status() accepts both legacy tx status entries and rate_info-based status entries, then turns the reported HT/VHT rate into a minstrel group and rate index. The validation helpers only checked that the entry was present and had tries recorded. They did not verify that the reported HT stream count, VHT NSS, VHT bandwidth encoding, and MCS value were representable by minstrel_ht's rate tables. As a result, malformed tx status metadata could produce group or rate indices outside the tables that minstrel_ht_get_stats() and minstrel_ht_ri_get_stats() index. Teach the existing tx status validation path to enforce the exact constraints used by minstrel HT's tables for both status formats. Reject HT rates beyond the supported stream groups, and reject VHT rates with unsupported bandwidth encodings, invalid NSS values, or MCS values outside the table. This keeps the fix at the existing trust boundary and leaves the stats lookup path unchanged. Fixes: ec8aa669b839 ("mac80211: add the minstrel_ht rate control algorithm") Cc: stable@kernel.org Reported-by: Yuan Tan Reported-by: Zhengchuan Liang Reported-by: Xin Liu Assisted-by: Codex:GPT-5.4 Signed-off-by: Yuqi Xu Signed-off-by: Ren Wei --- net/mac80211/rc80211_minstrel_ht.c | 47 +++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index b73ef3adfcc5..a35d42c77ac5 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -323,6 +323,43 @@ minstrel_ht_is_legacy_group(int group) group == MINSTREL_OFDM_GROUP; } +static bool +minstrel_ht_txstat_valid_rate(struct ieee80211_tx_rate *rate) +{ + unsigned int bw; + + if (rate->flags & IEEE80211_TX_RC_MCS) + return rate->idx < MINSTREL_MAX_STREAMS * 8; + + if (!(rate->flags & IEEE80211_TX_RC_VHT_MCS)) + return true; + + bw = !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + + 2 * !!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH); + + return !(rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) && + bw <= BW_80 && + ieee80211_rate_get_vht_nss(rate) <= MINSTREL_MAX_STREAMS && + ieee80211_rate_get_vht_mcs(rate) < MCS_GROUP_RATES; +} + +static bool +minstrel_ht_ri_txstat_valid_rate(struct rate_info *rate) +{ + if (rate->flags & RATE_INFO_FLAGS_MCS) + return rate->mcs < MINSTREL_MAX_STREAMS * 8; + + if (!(rate->flags & RATE_INFO_FLAGS_VHT_MCS)) + return true; + + return (rate->bw == RATE_INFO_BW_20 || + rate->bw == RATE_INFO_BW_40 || + rate->bw == RATE_INFO_BW_80) && + rate->nss >= 1 && + rate->nss <= MINSTREL_MAX_STREAMS && + rate->mcs < MCS_GROUP_RATES; +} + /* * Look up an MCS group index based on mac80211 rate information */ @@ -1205,8 +1242,9 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, if (!rate->count) return false; - if (rate->flags & IEEE80211_TX_RC_MCS || - rate->flags & IEEE80211_TX_RC_VHT_MCS) + if (rate->flags & IEEE80211_TX_RC_MCS || + rate->flags & IEEE80211_TX_RC_VHT_MCS) + return minstrel_ht_txstat_valid_rate(rate); for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) @@ -1235,8 +1273,9 @@ minstrel_ht_ri_txstat_valid(struct minstrel_priv *mp, if (!rate_status->try_count) return false; - if (rate_status->rate_idx.flags & RATE_INFO_FLAGS_MCS || - rate_status->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS) + if (rate_status->rate_idx.flags & RATE_INFO_FLAGS_MCS || + rate_status->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS) + return minstrel_ht_ri_txstat_valid_rate(&rate_status->rate_idx); for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) { -- 2.54.0