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 1075b29571 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 <jouni@qca.qualcomm.com>
This commit is contained in:
Vinay Krishna Eranna 2013-09-03 11:17:21 +03:00 committed by Jouni Malinen
parent ea0e92eef5
commit b2b688d18d
4 changed files with 19 additions and 5 deletions

View file

@ -505,11 +505,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
if (wpa_drv_associate(wpa_s, &params) < 0) { if (wpa_drv_associate(wpa_s, &params) < 0) {
wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); 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; return -1;
} }

View file

@ -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) void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
{ {
struct wpa_supplicant *wpa_s = ctx; struct wpa_supplicant *wpa_s = ctx;

View file

@ -161,6 +161,7 @@ void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer,
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s); void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s);
int wpas_p2p_4way_hs_failed(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 */ #else /* CONFIG_P2P */
static inline void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s) 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; return 0;
} }
static inline void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s)
{
}
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
#endif /* P2P_SUPPLICANT_H */ #endif /* P2P_SUPPLICANT_H */

View file

@ -1295,6 +1295,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
} }
if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) { if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
wpas_p2p_ap_setup_failed(wpa_s);
return; return;
} }
wpa_s->current_bss = bss; wpa_s->current_bss = bss;