aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant/events.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2015-02-08 09:38:56 (GMT)
committerJouni Malinen <j@w1.fi>2015-02-08 11:35:14 (GMT)
commitb0e669beebbb0d764c354f6ef7736c58f82681ec (patch)
treec0b3c4c56ba93bb0215cef073623d24e4dab4209 /wpa_supplicant/events.c
parent874057da4e11cf7a5e54e3360187d9342ea891a4 (diff)
downloadhostap-b0e669beebbb0d764c354f6ef7736c58f82681ec.zip
hostap-b0e669beebbb0d764c354f6ef7736c58f82681ec.tar.gz
hostap-b0e669beebbb0d764c354f6ef7736c58f82681ec.tar.bz2
P2P: Fix P2P_CONNECT-auto fallback to GO Neg with group interface
If a separate P2P group interface was used, P2P_CONNECT-auto fallback to GO Negotiation could result in use of freed memory and segmentation fault. This happened in cases where the peer GO was found in some old scans, but not in the first scan triggered by the P2P_CONNECT-auto command ("P2P: Peer was found running GO in older scan -> try to join the group" shows up in the debug log). In addition, the GO would still need to reply to PD Request to allow this code path to be triggered. When five scans for the GO were completed in this sequence, the P2P group interface was removed as part of falling back to GO Negotiation. However, that ended up dereferencing the freed wpa_s instance at the end of scan event processing. Fix this by reordering code a bit and breaking out from EVENT_SCAN_RESULTS processing if the interface could have been removed. Signed-off-by: Jouni Malinen <j@w1.fi>
Diffstat (limited to 'wpa_supplicant/events.c')
-rw-r--r--wpa_supplicant/events.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index ad55241..c4bc02d 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1448,7 +1448,12 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
int timeout_sec = wpa_s->scan_interval;
int timeout_usec = 0;
#ifdef CONFIG_P2P
- if (wpas_p2p_scan_no_go_seen(wpa_s) == 1)
+ int res;
+
+ res = wpas_p2p_scan_no_go_seen(wpa_s);
+ if (res == 2)
+ return 2;
+ if (res == 1)
return 0;
if (wpa_s->p2p_in_provisioning ||
@@ -1498,12 +1503,21 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
}
-static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
- union wpa_event_data *data)
+static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
{
struct wpa_supplicant *ifs;
+ int res;
- if (_wpa_supplicant_event_scan_results(wpa_s, data, 1) != 0) {
+ res = _wpa_supplicant_event_scan_results(wpa_s, data, 1);
+ if (res == 2) {
+ /*
+ * Interface may have been removed, so must not dereference
+ * wpa_s after this.
+ */
+ return 1;
+ }
+ if (res != 0) {
/*
* If no scan results could be fetched, then no need to
* notify those interfaces that did not actually request
@@ -1511,7 +1525,7 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
* interface, do not notify other interfaces to avoid concurrent
* operations during a connection attempt.
*/
- return;
+ return 0;
}
/*
@@ -1526,6 +1540,8 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
_wpa_supplicant_event_scan_results(ifs, data, 0);
}
}
+
+ return 0;
}
#endif /* CONFIG_NO_SCAN_PROCESSING */
@@ -3088,7 +3104,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_dbg(wpa_s, MSG_DEBUG, "Scan completed in %ld.%06ld seconds",
diff.sec, diff.usec);
}
- wpa_supplicant_event_scan_results(wpa_s, data);
+ if (wpa_supplicant_event_scan_results(wpa_s, data))
+ break; /* interface may have been removed */
wpa_s->own_scan_running = 0;
wpa_s->radio->external_scan_running = 0;
radio_work_check_next(wpa_s);