[PATCH] HE: fix he_capabilities size

John Crispin john at phrozen.org
Mon Jun 3 12:21:17 PDT 2019


The ppet field inside ieee80211_he_capabilities is of size [0]. The code
currently copies up to 12 additional bytes into the buffer, thus overwriting
memory. Fix this by verifying the size properly and using the passed length
value for allocation and the following memcpy() call.

Signed-off-by: John Crispin <john at phrozen.org>
---
 src/ap/ieee802_11_he.c | 39 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index ba22a174a..63270228f 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -44,6 +44,39 @@ static u8 ieee80211_he_ppet_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
 }
 
 
+static inline u8
+ieee80211_he_mcs_set_size(const u8 *phy_cap_info)
+{
+        u8 sz = 0;
+
+        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;
+        if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+	    (HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G | HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
+                sz += 4;
+
+        return sz;
+}
+
+static inline int ieee80211_check_he_cap_size(const u8 *buf, int len)
+{
+	struct ieee80211_he_capabilities *cap = (struct ieee80211_he_capabilities *)buf;
+	int cap_len = sizeof(struct ieee80211_he_capabilities);
+
+	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)
 {
 	struct ieee80211_he_capabilities *cap;
@@ -322,7 +355,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) ||
-	    he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
+	    ieee80211_check_he_cap_size(he_capab, he_capab_len)) {
 		sta->flags &= ~WLAN_STA_HE;
 		os_free(sta->he_capab);
 		sta->he_capab = NULL;
@@ -331,13 +364,13 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
 
 	if (!sta->he_capab) {
 		sta->he_capab =
-			os_zalloc(sizeof(struct ieee80211_he_capabilities));
+			os_zalloc(he_capab_len);
 		if (!sta->he_capab)
 			return WLAN_STATUS_UNSPECIFIED_FAILURE;
 	}
 
 	sta->flags |= WLAN_STA_HE;
-	os_memset(sta->he_capab, 0, sizeof(struct ieee80211_he_capabilities));
+	os_memset(sta->he_capab, 0, he_capab_len);
 	os_memcpy(sta->he_capab, he_capab, he_capab_len);
 	sta->he_capab_len = he_capab_len;
 
-- 
2.20.1




More information about the Hostap mailing list