]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
HE: Fix HE Capabilities element size
authorJohn Crispin <john@phrozen.org>
Tue, 13 Aug 2019 13:10:46 +0000 (15:10 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 30 Aug 2019 12:59:20 +0000 (15:59 +0300)
Set the max value of optional bytes inside the data structure. This
requires us to calculate the actually used size when copying the
HE capabilities and generating the IE.

Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Sven Eckelmann <seckelmann@datto.com>
src/ap/ieee802_11_he.c
src/common/ieee802_11_defs.h

index bb6083e8cb39069826db705e8c665b8850b96186..42b05d7ee2c46def01ded6311b20038d6fea809a 100644 (file)
@@ -44,6 +44,41 @@ static u8 ieee80211_he_ppet_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
 }
 
 
+static u8 ieee80211_he_mcs_set_size(const u8 *phy_cap_info)
+{
+       u8 sz = 4;
+
+       if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+           HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)
+               sz += 4;
+       if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+           HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
+               sz += 4;
+
+       return sz;
+}
+
+
+static int ieee80211_invalid_he_cap_size(const u8 *buf, size_t len)
+{
+       struct ieee80211_he_capabilities *cap;
+       size_t cap_len;
+
+       cap = (struct ieee80211_he_capabilities *) buf;
+       cap_len = sizeof(*cap) - sizeof(cap->optional);
+       if (len < cap_len)
+               return 1;
+
+       cap_len += ieee80211_he_mcs_set_size(cap->he_phy_capab_info);
+       if (len < cap_len)
+               return 1;
+
+       cap_len += ieee80211_he_ppet_size(buf[cap_len], cap->he_phy_capab_info);
+
+       return len != cap_len;
+}
+
+
 u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
                          enum ieee80211_op_mode opmode)
 {
@@ -56,7 +91,7 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
        if (!mode)
                return eid;
 
-       ie_size = sizeof(struct ieee80211_he_capabilities);
+       ie_size = sizeof(*cap) - sizeof(cap->optional);
        ppet_size = ieee80211_he_ppet_size(mode->he_capab[opmode].ppet[0],
                                           mode->he_capab[opmode].phy_cap);
 
@@ -324,6 +359,7 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
 {
        if (!he_capab || !hapd->iconf->ieee80211ax ||
            !check_valid_he_mcs(hapd, he_capab, opmode) ||
+           ieee80211_invalid_he_cap_size(he_capab, he_capab_len) ||
            he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
                sta->flags &= ~WLAN_STA_HE;
                os_free(sta->he_capab);
index b0aa913bbc9a73d8a4ec21ed5ce496b28030cd6d..214ba0e0f5f87acec2c72b83dc34254da567b91e 100644 (file)
@@ -2109,7 +2109,7 @@ struct ieee80211_he_capabilities {
        u8 he_phy_capab_info[11];
        /* Followed by 4, 8, or 12 octets of Supported HE-MCS And NSS Set field
        * and optional variable length PPE Thresholds field. */
-       u8 optional[];
+       u8 optional[37];
 } STRUCT_PACKED;
 
 struct ieee80211_he_operation {