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 <j@w1.fi>
This commit is contained in:
parent
edd5939a26
commit
a8826b1848
3 changed files with 10 additions and 1 deletions
|
@ -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)
|
static void interworking_reconnect(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
|
unsigned int tried;
|
||||||
|
|
||||||
if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
|
if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
|
||||||
wpa_supplicant_cancel_sched_scan(wpa_s);
|
wpa_supplicant_cancel_sched_scan(wpa_s);
|
||||||
wpa_supplicant_deauthenticate(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->disconnected = 0;
|
||||||
wpa_s->reassociate = 1;
|
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;
|
return;
|
||||||
|
|
||||||
|
wpa_s->interworking_fast_assoc_tried = 0;
|
||||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1002,6 +1002,9 @@ scan:
|
||||||
wpa_supplicant_req_scan(wpa_s, 1, 0);
|
wpa_supplicant_req_scan(wpa_s, 1, 0);
|
||||||
} else {
|
} else {
|
||||||
wpa_s->scan_for_connection = 0;
|
wpa_s->scan_for_connection = 0;
|
||||||
|
#ifdef CONFIG_INTERWORKING
|
||||||
|
wpa_s->interworking_fast_assoc_tried = 0;
|
||||||
|
#endif /* CONFIG_INTERWORKING */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -857,6 +857,7 @@ struct wpa_supplicant {
|
||||||
unsigned int network_select:1;
|
unsigned int network_select:1;
|
||||||
unsigned int auto_select:1;
|
unsigned int auto_select:1;
|
||||||
unsigned int auto_network_select:1;
|
unsigned int auto_network_select:1;
|
||||||
|
unsigned int interworking_fast_assoc_tried:1;
|
||||||
unsigned int fetch_all_anqp:1;
|
unsigned int fetch_all_anqp:1;
|
||||||
unsigned int fetch_osu_info:1;
|
unsigned int fetch_osu_info:1;
|
||||||
unsigned int fetch_osu_waiting_scan:1;
|
unsigned int fetch_osu_waiting_scan:1;
|
||||||
|
|
Loading…
Reference in a new issue