From: Jouni Malinen Date: Fri, 16 Jan 2015 23:43:00 +0000 (+0200) Subject: Interworking: Avoid busy loop in scan result mismatch corner cases X-Git-Tag: hostap_2_4~394 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8826b1848003eb84a6a287d4d71183ba2192dd6;p=thirdparty%2Fhostap.git Interworking: Avoid busy loop in scan result mismatch corner cases It was possible for interworking_find_network_match() to find a possible BSS match in a case where more thorough checks in wpa_supplicant_select_bss() reject network. This itself is fine, in general, but when combined with wpa_supplicant_fast_associate() optimization and auto_interworking=1, this resulted in a busy loop of up to five seconds and a possible stack overflow due to recursion in that loop. Fix this by limiting the Interworking wpa_supplicant_fast_associate() call to be used only once per scan iteration, so that new scan operations can be completed before going through the scan results again. Signed-off-by: Jouni Malinen --- diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 27c456118..f085c8906 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -73,6 +73,8 @@ static int cred_prio_cmp(const struct wpa_cred *a, const struct wpa_cred *b) static void interworking_reconnect(struct wpa_supplicant *wpa_s) { + unsigned int tried; + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_deauthenticate(wpa_s, @@ -80,10 +82,13 @@ static void interworking_reconnect(struct wpa_supplicant *wpa_s) } wpa_s->disconnected = 0; wpa_s->reassociate = 1; + tried = wpa_s->interworking_fast_assoc_tried; + wpa_s->interworking_fast_assoc_tried = 1; - if (wpa_supplicant_fast_associate(wpa_s) >= 0) + if (!tried && wpa_supplicant_fast_associate(wpa_s) >= 0) return; + wpa_s->interworking_fast_assoc_tried = 0; wpa_supplicant_req_scan(wpa_s, 0, 0); } diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index cb2c8d631..86fe2ba29 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1002,6 +1002,9 @@ scan: wpa_supplicant_req_scan(wpa_s, 1, 0); } else { wpa_s->scan_for_connection = 0; +#ifdef CONFIG_INTERWORKING + wpa_s->interworking_fast_assoc_tried = 0; +#endif /* CONFIG_INTERWORKING */ } } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index e396a5df6..2cb55ccb5 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -857,6 +857,7 @@ struct wpa_supplicant { unsigned int network_select:1; unsigned int auto_select:1; unsigned int auto_network_select:1; + unsigned int interworking_fast_assoc_tried:1; unsigned int fetch_all_anqp:1; unsigned int fetch_osu_info:1; unsigned int fetch_osu_waiting_scan:1;