EHT: Fix invalid length checking for EHT Capability element
Do not consider optional octets maximum lengths when validating EHT
fixed fields length. Furthermore, do not use the first two octets of the
PPE Thresholds field without explicitly confirming that these octets
were included in the element and fix PPE Thresholds field length
calculation.
Fixes: a6d1b4c46c
("EHT: Process (Re)Association Request frame capabilities")
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
This commit is contained in:
parent
6c7b2be424
commit
50d8837106
2 changed files with 20 additions and 22 deletions
|
@ -13,32 +13,25 @@
|
||||||
#include "ieee802_11.h"
|
#include "ieee802_11.h"
|
||||||
|
|
||||||
|
|
||||||
static u8 ieee80211_eht_ppet_size(const u8 *ppe_thres, const u8 *phy_cap_info)
|
static u16 ieee80211_eht_ppet_size(u16 ppe_thres_hdr, const u8 *phy_cap_info)
|
||||||
{
|
{
|
||||||
u8 sz = 0, nss, num_nss = 0;
|
u8 ru;
|
||||||
u32 ru;
|
u16 sz = 0;
|
||||||
|
|
||||||
if ((phy_cap_info[EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] &
|
if ((phy_cap_info[EHT_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] &
|
||||||
EHT_PHYCAP_PPE_THRESHOLD_PRESENT) == 0)
|
EHT_PHYCAP_PPE_THRESHOLD_PRESENT) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ru = (u32) ppe_thres[0];
|
ru = (ppe_thres_hdr &
|
||||||
ru = (ru & EHT_PPE_THRES_RU_INDEX_MASK) >> EHT_PPE_THRES_RU_INDEX_SHIFT;
|
EHT_PPE_THRES_RU_INDEX_MASK) >> EHT_PPE_THRES_RU_INDEX_SHIFT;
|
||||||
while (ru) {
|
while (ru) {
|
||||||
if (ru & 0x1)
|
if (ru & 0x1)
|
||||||
sz++;
|
sz++;
|
||||||
ru >>= 1;
|
ru >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nss = (ppe_thres[0] & EHT_PPE_THRES_NSS_MASK) >>
|
sz = sz * (1 + ((ppe_thres_hdr & EHT_PPE_THRES_NSS_MASK) >>
|
||||||
EHT_PPE_THRES_NSS_SHIFT;
|
EHT_PPE_THRES_NSS_SHIFT));
|
||||||
while (nss) {
|
|
||||||
if (nss & 0x1)
|
|
||||||
num_nss++;
|
|
||||||
nss >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sz = sz * (1 + num_nss);
|
|
||||||
sz = (sz * 6) + 9;
|
sz = (sz * 6) + 9;
|
||||||
if (sz % 8)
|
if (sz % 8)
|
||||||
sz += 8;
|
sz += 8;
|
||||||
|
@ -90,7 +83,8 @@ size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
|
||||||
|
|
||||||
len += ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
|
len += ieee80211_eht_mcs_set_size(mode->he_capab[opmode].phy_cap,
|
||||||
eht_cap->phy_cap);
|
eht_cap->phy_cap);
|
||||||
len += ieee80211_eht_ppet_size(eht_cap->ppet, eht_cap->phy_cap);
|
len += ieee80211_eht_ppet_size(WPA_GET_LE16(&eht_cap->ppet[0]),
|
||||||
|
eht_cap->phy_cap);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -146,8 +140,9 @@ u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid,
|
||||||
pos += mcs_nss_len;
|
pos += mcs_nss_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppe_thresh_len = ieee80211_eht_ppet_size(eht_cap->ppet,
|
ppe_thresh_len = ieee80211_eht_ppet_size(
|
||||||
eht_cap->phy_cap);
|
WPA_GET_LE16(&eht_cap->ppet[0]),
|
||||||
|
eht_cap->phy_cap);
|
||||||
if (ppe_thresh_len) {
|
if (ppe_thresh_len) {
|
||||||
os_memcpy(pos, eht_cap->ppet, ppe_thresh_len);
|
os_memcpy(pos, eht_cap->ppet, ppe_thresh_len);
|
||||||
pos += ppe_thresh_len;
|
pos += ppe_thresh_len;
|
||||||
|
@ -289,11 +284,12 @@ static bool ieee80211_invalid_eht_cap_size(const u8 *he_cap, const u8 *eht_cap,
|
||||||
struct ieee80211_eht_capabilities *cap;
|
struct ieee80211_eht_capabilities *cap;
|
||||||
const u8 *he_phy_cap;
|
const u8 *he_phy_cap;
|
||||||
size_t cap_len;
|
size_t cap_len;
|
||||||
|
u16 ppe_thres_hdr;
|
||||||
|
|
||||||
he_capab = (const struct ieee80211_he_capabilities *) he_cap;
|
he_capab = (const struct ieee80211_he_capabilities *) he_cap;
|
||||||
he_phy_cap = he_capab->he_phy_capab_info;
|
he_phy_cap = he_capab->he_phy_capab_info;
|
||||||
cap = (struct ieee80211_eht_capabilities *) eht_cap;
|
cap = (struct ieee80211_eht_capabilities *) eht_cap;
|
||||||
cap_len = sizeof(*cap);
|
cap_len = sizeof(*cap) - sizeof(cap->optional);
|
||||||
if (len < cap_len)
|
if (len < cap_len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -301,7 +297,9 @@ static bool ieee80211_invalid_eht_cap_size(const u8 *he_cap, const u8 *eht_cap,
|
||||||
if (len < cap_len)
|
if (len < cap_len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
cap_len += ieee80211_eht_ppet_size(&eht_cap[cap_len], cap->phy_cap);
|
ppe_thres_hdr = len > cap_len + 1 ?
|
||||||
|
WPA_GET_LE16(&eht_cap[cap_len]) : 0x01ff;
|
||||||
|
cap_len += ieee80211_eht_ppet_size(ppe_thres_hdr, cap->phy_cap);
|
||||||
|
|
||||||
return len < cap_len;
|
return len < cap_len;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2495,9 +2495,9 @@ struct ieee80211_eht_operation {
|
||||||
#define EHT_PPE_THRES_NSS_MASK ((u8) (BIT(0) | BIT(1) | \
|
#define EHT_PPE_THRES_NSS_MASK ((u8) (BIT(0) | BIT(1) | \
|
||||||
BIT(2) | BIT(3)))
|
BIT(2) | BIT(3)))
|
||||||
#define EHT_PPE_THRES_RU_INDEX_SHIFT 4
|
#define EHT_PPE_THRES_RU_INDEX_SHIFT 4
|
||||||
#define EHT_PPE_THRES_RU_INDEX_MASK ((u8) (BIT(4) | BIT(5) | \
|
#define EHT_PPE_THRES_RU_INDEX_MASK ((u16) (BIT(4) | BIT(5) | \
|
||||||
BIT(6) | BIT(7) | \
|
BIT(6) | BIT(7) | \
|
||||||
BIT(8)))
|
BIT(8)))
|
||||||
|
|
||||||
#define EHT_NSS_MAX_STREAMS 8
|
#define EHT_NSS_MAX_STREAMS 8
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue