P2P: Fix crash when failed to create GO interface aosp-kk-from-upstream
authorVinay Krishna Eranna <c_veran@qti.qualcomm.com>
Tue, 3 Sep 2013 08:17:21 +0000 (11:17 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 3 Sep 2013 09:43:12 +0000 (12:43 +0300)
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 <jouni@qca.qualcomm.com>

wpa_supplicant/ap.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h
wpa_supplicant/wpa_supplicant.c

index c2fb215..fdbe248 100644 (file)
@@ -505,11 +505,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
 
        if (wpa_drv_associate(wpa_s, &params) < 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;
        }
 
index 4b941c7..9338ad5 100644 (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)
 {
        struct wpa_supplicant *wpa_s = ctx;
index c718fba..26f5def 100644 (file)
@@ -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 */
index c274f3c..334ccc9 100644 (file)
@@ -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;