From f4de21a77afc113fe959133ca4e873235a754025 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 4 Nov 2020 19:50:34 +0200 Subject: [PATCH] BSS/scan: More conversions to for_each_element_id() Use the common IE parsing routine in hope of trying to make the length checks easier for static analyzers. In addition, try to make the *_vendor_ie_multi() cases easier to analyze as well even though they cannot use for_each_element_id(). Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 35 ++++++++++++++++------------- wpa_supplicant/scan.c | 52 +++++++++++++++++++++---------------------- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 97aa146c8..7b6ed773a 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -1184,22 +1184,20 @@ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; if (bss->beacon_ie_len == 0) return NULL; - pos = (const u8 *) (bss + 1); - pos += bss->ie_len; - end = pos + bss->beacon_ie_len; + ies = (const u8 *) (bss + 1); + ies += bss->ie_len; - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, + bss->beacon_ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1230,12 +1228,17 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, end = pos + bss->ie_len; while (end - pos > 1) { - if (2 + pos[1] > end - pos) + u8 ie, len; + + ie = pos[0]; + len = pos[1]; + if (len > end - pos - 2) break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); - pos += 2 + pos[1]; + pos += 2; + if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 && + vendor_type == WPA_GET_BE32(pos)) + wpabuf_put_data(buf, pos + 4, len - 4); + pos += len; } if (wpabuf_len(buf) == 0) { diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index b9e4162c8..78371d3ad 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1869,18 +1869,15 @@ const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; + ies = (const u8 *) (res + 1); - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, res->ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1902,22 +1899,20 @@ const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; if (res->beacon_ie_len == 0) return NULL; - pos = (const u8 *) (res + 1); - pos += res->ie_len; - end = pos + res->beacon_ie_len; + ies = (const u8 *) (res + 1); + ies += res->ie_len; - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, + res->beacon_ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1948,12 +1943,17 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, end = pos + res->ie_len; while (end - pos > 1) { - if (2 + pos[1] > end - pos) + u8 ie, len; + + ie = pos[0]; + len = pos[1]; + if (len > end - pos - 2) break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); - pos += 2 + pos[1]; + pos += 2; + if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 && + vendor_type == WPA_GET_BE32(pos)) + wpabuf_put_data(buf, pos + 4, len - 4); + pos += len; } if (wpabuf_len(buf) == 0) {