wifi: mt76: mt76x02: validate TX-status rate index before mac80211 handoff

mt76x02_mac_process_tx_rate() extracts the rate index straight from
the hardware's raw TX-status word with no bounds check for the
HT/HT_GF/VHT cases, and mt76x02_mac_fill_tx_status() ignores its
return value. A stale or corrupt hardware index reaches mac80211's
minstrel_ht rate control, whose per-group rate array is a fixed 10
entries (MCS_GROUP_RATES), causing an out-of-bounds write.

Validate the index in mt76x02_mac_process_tx_rate() (HT: 0-31,
VHT: MCS nibble 0-9) and have mt76x02_mac_fill_tx_status() bail out
cleanly on failure instead of passing an invalid index through.

Fixes: 7c1f88812690 ("mt76: unify send_tx_status and related helpers")
Cc: [email protected]
Tested-by: Devin Wittmayer <[email protected]>
Signed-off-by: Mark Anthony Agarro <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Mark Anthony Agarro
2026-09-01 13:25:05 +02:00
committed by Felix Fietkau
parent 4d82c99620
commit 0789c43c1a
+13 -6
View File
@@ -302,10 +302,14 @@ mt76x02_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD;
fallthrough;
case MT_PHY_TYPE_HT:
if (idx > 31)
return -EINVAL;
txrate->flags |= IEEE80211_TX_RC_MCS;
txrate->idx = idx;
break;
case MT_PHY_TYPE_VHT:
if ((idx & 0xf) > 9)
return -EINVAL;
txrate->flags |= IEEE80211_TX_RC_VHT_MCS;
txrate->idx = idx;
break;
@@ -493,18 +497,21 @@ mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, struct mt76x02_sta *msta,
first_rate = st->rate & ~MT_PKTID_RATE;
first_rate |= st->pktid & MT_PKTID_RATE;
mt76x02_mac_process_tx_rate(&rate[0], first_rate,
dev->mphy.chandef.chan->band);
if (mt76x02_mac_process_tx_rate(&rate[0], first_rate,
dev->mphy.chandef.chan->band))
return;
} else if (rate[0].idx < 0) {
if (!msta)
return;
mt76x02_mac_process_tx_rate(&rate[0], msta->wcid.tx_info,
dev->mphy.chandef.chan->band);
if (mt76x02_mac_process_tx_rate(&rate[0], msta->wcid.tx_info,
dev->mphy.chandef.chan->band))
return;
}
mt76x02_mac_process_tx_rate(&last_rate, st->rate,
dev->mphy.chandef.chan->band);
if (mt76x02_mac_process_tx_rate(&last_rate, st->rate,
dev->mphy.chandef.chan->band))
return;
for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) {
retry--;