BACKPORT: 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> Bug: 253289327 Change-Id: I40a3f916cf6bb26ab0e7e36fbb32fefefeb3645b (cherry picked from commit ea5cba269fb1fe22b84f4d01bb3d56320e6ffa3e) [Kiran Kumar Lokere: Skipped changes in net/mac80211 due to missing dependency changes] Signed-off-by: Kiran Kumar Lokere <quic_klokere@quicinc.com> Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com> Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
committed by
Carlos Llamas
parent
22428dd3fd
commit
d1e18aab78
@@ -2805,7 +2805,8 @@ ieee80211_he_spr_size(const u8 *he_spr_ie)
|
||||
/* Calculate 802.11be EHT capabilities IE Tx/Rx EHT MCS NSS Support Field size */
|
||||
static inline u8
|
||||
ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap,
|
||||
const struct ieee80211_eht_cap_elem_fixed *eht_cap)
|
||||
const struct ieee80211_eht_cap_elem_fixed *eht_cap,
|
||||
bool from_ap)
|
||||
{
|
||||
u8 count = 0;
|
||||
|
||||
@@ -2826,7 +2827,10 @@ ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap,
|
||||
if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
|
||||
count += 3;
|
||||
|
||||
return count ? count : 4;
|
||||
if (count)
|
||||
return count;
|
||||
|
||||
return from_ap ? 3 : 4;
|
||||
}
|
||||
|
||||
/* 802.11be EHT PPE Thresholds */
|
||||
@@ -2862,7 +2866,8 @@ ieee80211_eht_ppe_size(u16 ppe_thres_hdr, const u8 *phy_cap_info)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len)
|
||||
ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len,
|
||||
bool from_ap)
|
||||
{
|
||||
const struct ieee80211_eht_cap_elem_fixed *elem = (const void *)data;
|
||||
u8 needed = sizeof(struct ieee80211_eht_cap_elem_fixed);
|
||||
@@ -2871,7 +2876,8 @@ ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len)
|
||||
return false;
|
||||
|
||||
needed += ieee80211_eht_mcs_nss_size((const void *)he_capa,
|
||||
(const void *)data);
|
||||
(const void *)data,
|
||||
from_ap);
|
||||
if (len < needed)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -15966,7 +15973,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