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:
Johannes Berg
2022-08-16 11:26:23 +02:00
committed by Carlos Llamas
parent 22428dd3fd
commit d1e18aab78
3 changed files with 39 additions and 9 deletions

View File

@@ -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;

View File

@@ -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))

View File

@@ -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;
}
}