mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 18:28:23 -05:00
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>
This commit is contained in:
parent
874057da4e
commit
b0e669beeb
@ -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,
|
||||
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);
|
||||
|
@ -117,7 +117,7 @@ static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
|
||||
static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
|
||||
void *timeout_ctx);
|
||||
static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx);
|
||||
static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||
static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||
int group_added);
|
||||
static void wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
|
||||
static void wpas_stop_listen(void *ctx);
|
||||
@ -8184,16 +8184,18 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
|
||||
}
|
||||
|
||||
|
||||
static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||
static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||
int group_added)
|
||||
{
|
||||
struct wpa_supplicant *group = wpa_s;
|
||||
int ret = 0;
|
||||
|
||||
if (wpa_s->global->p2p_group_formation)
|
||||
group = wpa_s->global->p2p_group_formation;
|
||||
wpa_s = wpa_s->parent;
|
||||
offchannel_send_action_done(wpa_s);
|
||||
if (group_added)
|
||||
wpas_p2p_group_delete(group, P2P_GROUP_REMOVAL_SILENT);
|
||||
ret = wpas_p2p_group_delete(group, P2P_GROUP_REMOVAL_SILENT);
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Fall back to GO Negotiation");
|
||||
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin,
|
||||
wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
|
||||
@ -8202,11 +8204,14 @@ static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||
wpa_s->p2p_pd_before_go_neg,
|
||||
wpa_s->p2p_go_ht40,
|
||||
wpa_s->p2p_go_vht);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!wpa_s->p2p_fallback_to_go_neg ||
|
||||
wpa_s->p2p_in_provisioning <= 5)
|
||||
return 0;
|
||||
@ -8216,9 +8221,9 @@ int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s)
|
||||
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - "
|
||||
"fallback to GO Negotiation");
|
||||
wpas_p2p_fallback_to_go_neg(wpa_s, 1);
|
||||
res = wpas_p2p_fallback_to_go_neg(wpa_s, 1);
|
||||
|
||||
return 1;
|
||||
return res == 1 ? 2 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user