wifi: mac80211: limit injected HT/VHT MCSes

With radiotap injection the HT/VHT MCSes can be just
about anything, but that can later get problematic.

Limit them to the rates the device reports, which is
presumably going to be a subset of what mac80211 can
do, except for HT MCS 32 which some devices report as
supported, but then TX status can't deal with it.

If it's not supported just ignore the config.

Assisted-by: LLM
Fixes: dfdfc2beb0 ("mac80211: Parse legacy and HT rate in injected frames")
Fixes: 646e76bb5d ("mac80211: parse VHT info in injected frames")
Link: https://patch.msgid.link/20261005224950.68e210b8487a.I2ee0e4664c54cf31002eb9e4f5190fd05ff4130f@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2026-10-05 22:47:57 +02:00
parent e3cf8da7e0
commit 22d8e38161

View File

@ -2172,6 +2172,27 @@ static bool ieee80211_rate_bw_usable(u16 rate_flags,
return width <= cfg80211_chandef_get_width(chandef);
}
static bool
ieee80211_vht_tx_rate_supported(const struct ieee80211_sta_vht_cap *vht_cap,
u8 mcs, u8 nss)
{
u16 map = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
if (!vht_cap->vht_supported)
return false;
switch ((map >> (2 * (nss - 1))) & 3) {
case IEEE80211_VHT_MCS_SUPPORT_0_7:
return mcs <= 7;
case IEEE80211_VHT_MCS_SUPPORT_0_8:
return mcs <= 8;
case IEEE80211_VHT_MCS_SUPPORT_0_9:
return mcs <= 9;
default:
return false;
}
}
bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
struct net_device *dev,
const struct cfg80211_chan_def *chandef,
@ -2368,14 +2389,20 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
hweight8(info->control.antennas))
info->control.antennas = 0;
info->control.rates[0].idx = rate;
/* MCS 32 and up aren't handled, e.g. by TX status */
if (sband && sband->ht_cap.ht_supported && rate < 32 &&
sband->ht_cap.mcs.rx_mask[rate / 8] & BIT(rate % 8))
info->control.rates[0].idx = rate;
} else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
/* reset antennas if not enough */
if (vht_nss > hweight8(info->control.antennas))
info->control.antennas = 0;
ieee80211_rate_set_vht(info->control.rates, vht_mcs,
vht_nss);
if (sband &&
ieee80211_vht_tx_rate_supported(&sband->vht_cap,
vht_mcs, vht_nss))
ieee80211_rate_set_vht(info->control.rates,
vht_mcs, vht_nss);
} else if (sband) {
for (i = 0; i < sband->n_bitrates; i++) {
if (rate * 5 != sband->bitrates[i].bitrate)