mirror of
https://github.com/torvalds/linux.git
synced 2026-05-05 23:05:25 -04:00
wifi: cfg80211/mac80211: check EHT capability size correctly
For AP/non-AP the EHT MCS/NSS subfield size differs, the 4-octet subfield is only used for 20 MHz-only non-AP STA. Pass an argument around everywhere to be able to parse it properly. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
@@ -860,6 +860,9 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
|
||||
for (i = 0; i < sband->n_iftype_data; i++) {
|
||||
const struct ieee80211_sband_iftype_data *iftd;
|
||||
bool has_ap, has_non_ap;
|
||||
u32 ap_bits = BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
|
||||
iftd = &sband->iftype_data[i];
|
||||
|
||||
@@ -879,6 +882,19 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
else
|
||||
have_he = have_he &&
|
||||
iftd->he_cap.has_he;
|
||||
|
||||
has_ap = iftd->types_mask & ap_bits;
|
||||
has_non_ap = iftd->types_mask & ~ap_bits;
|
||||
|
||||
/*
|
||||
* For EHT 20 MHz STA, the capabilities format differs
|
||||
* but to simplify, don't check 20 MHz but rather check
|
||||
* only if AP and non-AP were mentioned at the same time,
|
||||
* reject if so.
|
||||
*/
|
||||
if (WARN_ON(iftd->eht_cap.has_eht &&
|
||||
has_ap && has_non_ap))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (WARN_ON(!have_he && band == NL80211_BAND_6GHZ))
|
||||
|
||||
@@ -1820,10 +1820,15 @@ nl80211_send_iftype_data(struct sk_buff *msg,
|
||||
if (eht_cap->has_eht && he_cap->has_he) {
|
||||
u8 mcs_nss_size, ppe_thresh_size;
|
||||
u16 ppe_thres_hdr;
|
||||
bool is_ap;
|
||||
|
||||
is_ap = iftdata->types_mask & BIT(NL80211_IFTYPE_AP) ||
|
||||
iftdata->types_mask & BIT(NL80211_IFTYPE_P2P_GO);
|
||||
|
||||
mcs_nss_size =
|
||||
ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
|
||||
&eht_cap->eht_cap_elem);
|
||||
&eht_cap->eht_cap_elem,
|
||||
is_ap);
|
||||
|
||||
ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]);
|
||||
ppe_thresh_size =
|
||||
@@ -5668,7 +5673,7 @@ static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
|
||||
params->eht_cap = (void *)(cap->data + 1);
|
||||
if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap,
|
||||
(const u8 *)params->eht_cap,
|
||||
cap->datalen - 1))
|
||||
cap->datalen - 1, true))
|
||||
return -EINVAL;
|
||||
}
|
||||
cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len);
|
||||
@@ -6897,7 +6902,8 @@ static int nl80211_set_station_tdls(struct genl_info *info,
|
||||
|
||||
if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa,
|
||||
(const u8 *)params->link_sta_params.eht_capa,
|
||||
params->link_sta_params.eht_capa_len))
|
||||
params->link_sta_params.eht_capa_len,
|
||||
false))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -7208,7 +7214,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa,
|
||||
(const u8 *)params.link_sta_params.eht_capa,
|
||||
params.link_sta_params.eht_capa_len))
|
||||
params.link_sta_params.eht_capa_len,
|
||||
false))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -15968,7 +15975,8 @@ nl80211_add_mod_link_station(struct sk_buff *skb, struct genl_info *info,
|
||||
|
||||
if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa,
|
||||
(const u8 *)params.eht_capa,
|
||||
params.eht_capa_len))
|
||||
params.eht_capa_len,
|
||||
false))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user