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 */
|
/* Calculate 802.11be EHT capabilities IE Tx/Rx EHT MCS NSS Support Field size */
|
||||||
static inline u8
|
static inline u8
|
||||||
ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap,
|
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;
|
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)
|
if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
|
||||||
count += 3;
|
count += 3;
|
||||||
|
|
||||||
return count ? count : 4;
|
if (count)
|
||||||
|
return count;
|
||||||
|
|
||||||
|
return from_ap ? 3 : 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 802.11be EHT PPE Thresholds */
|
/* 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
|
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;
|
const struct ieee80211_eht_cap_elem_fixed *elem = (const void *)data;
|
||||||
u8 needed = sizeof(struct ieee80211_eht_cap_elem_fixed);
|
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;
|
return false;
|
||||||
|
|
||||||
needed += ieee80211_eht_mcs_nss_size((const void *)he_capa,
|
needed += ieee80211_eht_mcs_nss_size((const void *)he_capa,
|
||||||
(const void *)data);
|
(const void *)data,
|
||||||
|
from_ap);
|
||||||
if (len < needed)
|
if (len < needed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -860,6 +860,9 @@ int wiphy_register(struct wiphy *wiphy)
|
|||||||
|
|
||||||
for (i = 0; i < sband->n_iftype_data; i++) {
|
for (i = 0; i < sband->n_iftype_data; i++) {
|
||||||
const struct ieee80211_sband_iftype_data *iftd;
|
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];
|
iftd = &sband->iftype_data[i];
|
||||||
|
|
||||||
@@ -879,6 +882,19 @@ int wiphy_register(struct wiphy *wiphy)
|
|||||||
else
|
else
|
||||||
have_he = have_he &&
|
have_he = have_he &&
|
||||||
iftd->he_cap.has_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))
|
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) {
|
if (eht_cap->has_eht && he_cap->has_he) {
|
||||||
u8 mcs_nss_size, ppe_thresh_size;
|
u8 mcs_nss_size, ppe_thresh_size;
|
||||||
u16 ppe_thres_hdr;
|
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 =
|
mcs_nss_size =
|
||||||
ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
|
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_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]);
|
||||||
ppe_thresh_size =
|
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);
|
params->eht_cap = (void *)(cap->data + 1);
|
||||||
if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap,
|
if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap,
|
||||||
(const u8 *)params->eht_cap,
|
(const u8 *)params->eht_cap,
|
||||||
cap->datalen - 1))
|
cap->datalen - 1, true))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len);
|
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,
|
if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa,
|
||||||
(const u8 *)params->link_sta_params.eht_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;
|
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,
|
if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa,
|
||||||
(const u8 *)params.link_sta_params.eht_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;
|
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,
|
if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa,
|
||||||
(const u8 *)params.eht_capa,
|
(const u8 *)params.eht_capa,
|
||||||
params.eht_capa_len))
|
params.eht_capa_len,
|
||||||
|
false))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user