From b2b688d18d40cd667d0faa149b4a7172166b3bd4 Mon Sep 17 00:00:00 2001 From: Vinay Krishna Eranna Date: Tue, 3 Sep 2013 11:17:21 +0300 Subject: [PATCH] P2P: Fix crash when failed to create GO interface wpa_supplicant crashes if driver configuration for AP mode interface configuration fails after group negotiation. This is because of a regression from commit 1075b2957169d8f9d6dddd7679339c751dc9515b that ends up freeing the wpa_s instance from within wpa_supplicant_create_ap() without the caller knowing. Fix this by using an eloop timeout to free remove the P2P group so that wpa_supplicant_create_ap() and especially wpa_supplicant_associate() callers do not need to know about interface getting possibly removed. In addition, move the P2P specific code into p2p_supplicant.c where it really belongs. This allows the already existing group formation timeout to be used by reducing the timeout to zero. Signed-hostap: Jouni Malinen --- wpa_supplicant/ap.c | 5 ----- wpa_supplicant/p2p_supplicant.c | 12 ++++++++++++ wpa_supplicant/p2p_supplicant.h | 5 +++++ wpa_supplicant/wpa_supplicant.c | 2 ++ 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index c2fb2156a..fdbe248a7 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -505,11 +505,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); -#ifdef CONFIG_P2P - if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION && - wpa_s->global->p2p_group_formation == wpa_s) - wpas_p2p_group_formation_failed(wpa_s->parent); -#endif /* CONFIG_P2P */ return -1; } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 4b941c7f9..9338ad5b0 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1258,6 +1258,18 @@ void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s) } +void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->global->p2p_group_formation != wpa_s) + return; + /* Speed up group formation timeout since this cannot succeed */ + eloop_cancel_timeout(wpas_p2p_group_formation_timeout, + wpa_s->parent, NULL); + eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout, + wpa_s->parent, NULL); +} + + void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) { struct wpa_supplicant *wpa_s = ctx; diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index c718fba88..26f5def4e 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -161,6 +161,7 @@ void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer, #ifdef CONFIG_P2P void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s); int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s); +void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s); #else /* CONFIG_P2P */ static inline void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s) { @@ -170,6 +171,10 @@ static inline int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s) { return 0; } + +static inline void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s) +{ +} #endif /* CONFIG_P2P */ #endif /* P2P_SUPPLICANT_H */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index c274f3c81..334ccc93c 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1295,6 +1295,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, } if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) + wpas_p2p_ap_setup_failed(wpa_s); return; } wpa_s->current_bss = bss;