aboutsummaryrefslogtreecommitdiffstats
path: root/src/ap/ieee802_11_ht.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2014-12-22 19:54:11 (GMT)
committerJouni Malinen <j@w1.fi>2014-12-22 19:54:11 (GMT)
commit0acc2c809d86e4c7b18baca35bed5717e4d50208 (patch)
treee9ff2db7718a9201c7294b5b2db7154ec3ddb1f9 /src/ap/ieee802_11_ht.c
parent2a32ad66da9e2b318bc994222441cdd38d2ef7ec (diff)
downloadhostap-0acc2c809d86e4c7b18baca35bed5717e4d50208.zip
hostap-0acc2c809d86e4c7b18baca35bed5717e4d50208.tar.gz
hostap-0acc2c809d86e4c7b18baca35bed5717e4d50208.tar.bz2
HT: More robust 20/40 coex Action frame parsing
Commit 587d60d2b74190d58ddeb6a30ab338352af1186a ('Add AP mode support for HT 20/40 co-ex Action frame') added processing of co-ex report, but did not include proper bounds checking or IE type checking for the payload. Furthermore, this was not ready for the possible extensibility of the 20/40 BSS Coexistence element. Fix these by checking IE ids for both elements and doing more apprioriate bounds checking for the element lengths to avoid potentially reading beyond the frame buffer. Though, the event receive buffer in both libnl and driver_nl80211_monitor.c is sufficiently large to make it very unlikely that the maximum read of about 260 bytes beyond the end of the Action frame would really have any chances of hitting the end of the memory buffer, so the practical effect of missing bounds checking would have been possibly accepting an invalid report frame and moving to 20 MHz channel unnecessarily. Signed-off-by: Jouni Malinen <j@w1.fi>
Diffstat (limited to 'src/ap/ieee802_11_ht.c')
-rw-r--r--src/ap/ieee802_11_ht.c48
1 files changed, 36 insertions, 12 deletions
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index f549421..3f299f3 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -211,7 +211,8 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
struct ieee80211_2040_intol_chan_report *ic_report;
int is_ht_allowed = 1;
int i;
- const u8 *data = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 1;
+ const u8 *start = (const u8 *) mgmt;
+ const u8 *data = start + IEEE80211_HDRLEN + 2;
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "hostapd_public_action - action=%d",
@@ -220,14 +221,22 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
if (!(iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
return;
- if (len < IEEE80211_HDRLEN + 1)
+ if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie))
return;
- data++;
- bc_ie = (struct ieee80211_2040_bss_coex_ie *) &data[0];
- ic_report = (struct ieee80211_2040_intol_chan_report *)
- (&data[0] + sizeof(*bc_ie));
+ bc_ie = (struct ieee80211_2040_bss_coex_ie *) data;
+ if (bc_ie->element_id != WLAN_EID_20_40_BSS_COEXISTENCE ||
+ bc_ie->length < 1) {
+ wpa_printf(MSG_DEBUG, "Unexpected IE (%u,%u) in coex report",
+ bc_ie->element_id, bc_ie->length);
+ return;
+ }
+ if (len < IEEE80211_HDRLEN + 2 + 2 + bc_ie->length)
+ return;
+ data += 2 + bc_ie->length;
+ wpa_printf(MSG_DEBUG, "20/40 BSS Coexistence Information field: 0x%x",
+ bc_ie->coex_param);
if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) {
hostapd_logger(hapd, mgmt->sa,
HOSTAPD_MODULE_IEEE80211,
@@ -244,22 +253,34 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
is_ht_allowed = 0;
}
- if (ic_report &&
- (ic_report->element_id == WLAN_EID_20_40_BSS_INTOLERANT)) {
+ if (start + len - data >= 3 &&
+ data[0] == WLAN_EID_20_40_BSS_INTOLERANT && data[1] >= 1) {
+ u8 ielen = data[1];
+
+ if (ielen > start + len - data - 2)
+ return;
+ ic_report = (struct ieee80211_2040_intol_chan_report *) data;
+ wpa_printf(MSG_DEBUG,
+ "20/40 BSS Intolerant Channel Report: Operating Class %u",
+ ic_report->op_class);
+
/* Go through the channel report to find any BSS there in the
* affected channel range */
- for (i = 0; i < ic_report->length - 1; i++) {
- if (is_40_allowed(iface, ic_report->variable[i]))
+ for (i = 0; i < ielen - 1; i++) {
+ u8 chan = ic_report->variable[i];
+
+ if (is_40_allowed(iface, chan))
continue;
hostapd_logger(hapd, mgmt->sa,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"20_40_INTOLERANT channel %d reported",
- ic_report->variable[i]);
+ chan);
is_ht_allowed = 0;
- break;
}
}
+ wpa_printf(MSG_DEBUG, "is_ht_allowed=%d num_sta_ht40_intolerant=%d",
+ is_ht_allowed, iface->num_sta_ht40_intolerant);
if (!is_ht_allowed &&
(iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) {
@@ -279,6 +300,9 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
NULL);
eloop_register_timeout(delay_time, 0, ap_ht2040_timeout,
hapd->iface, NULL);
+ wpa_printf(MSG_DEBUG,
+ "Reschedule HT 20/40 timeout to occur in %u seconds",
+ delay_time);
}
}
}