]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
D-Bus: Share 'remove all networks' with CLI
authorBrian Norris <briannorris@chromium.org>
Thu, 20 Aug 2020 02:09:35 +0000 (19:09 -0700)
committerJouni Malinen <j@w1.fi>
Sat, 10 Oct 2020 17:39:00 +0000 (20:39 +0300)
The D-Bus implementation of RemoveAllNetworks differs wildly from the
CLI implementation. Let's share the implementations.

This resolves use-after-free bugs I noticed, where we continue to use
the 'wpa_s->current_ssid' wpa_ssid object after freeing it, because we
didn't bother to disconnect from (and set to NULL) current_ssid before
freeing it.

Signed-off-by: Brian Norris <briannorris@chromium.org>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 1bb18bdd11ad3a71bb5e4cc21ef04a9140fb9b75..76a3ed618e5eccd6c25c87e2cd6983ba5fda557c 100644 (file)
@@ -3480,38 +3480,12 @@ static int wpa_supplicant_ctrl_iface_remove_network(
        struct wpa_supplicant *wpa_s, char *cmd)
 {
        int id;
-       struct wpa_ssid *ssid;
        int result;
 
        /* cmd: "<network id>" or "all" */
        if (os_strcmp(cmd, "all") == 0) {
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
-               if (wpa_s->sched_scanning)
-                       wpa_supplicant_cancel_sched_scan(wpa_s);
-
-               eapol_sm_invalidate_cached_session(wpa_s->eapol);
-               if (wpa_s->current_ssid) {
-#ifdef CONFIG_SME
-                       wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
-                       wpa_sm_set_config(wpa_s->wpa, NULL);
-                       eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
-                       if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
-                               wpa_s->own_disconnect_req = 1;
-                       wpa_supplicant_deauthenticate(
-                               wpa_s, WLAN_REASON_DEAUTH_LEAVING);
-               }
-               ssid = wpa_s->conf->ssid;
-               while (ssid) {
-                       struct wpa_ssid *remove_ssid = ssid;
-                       id = ssid->id;
-                       ssid = ssid->next;
-                       if (wpa_s->last_ssid == remove_ssid)
-                               wpa_s->last_ssid = NULL;
-                       wpas_notify_network_removed(wpa_s, remove_ssid);
-                       wpa_config_remove_network(wpa_s->conf, id);
-               }
-               return 0;
+               return wpa_supplicant_remove_all_networks(wpa_s);
        }
 
        id = atoi(cmd);
index 489d89a8def0806567380f452c6f7984833b50c3..86f85605ac3658a13b6f4a304b4377844e84812f 100644 (file)
@@ -1817,25 +1817,6 @@ out:
 }
 
 
-static void remove_network(void *arg, struct wpa_ssid *ssid)
-{
-       struct wpa_supplicant *wpa_s = arg;
-
-       wpas_notify_network_removed(wpa_s, ssid);
-
-       if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
-               wpa_printf(MSG_ERROR,
-                          "%s[dbus]: error occurred when removing network %d",
-                          __func__, ssid->id);
-               return;
-       }
-
-       if (ssid == wpa_s->current_ssid)
-               wpa_supplicant_deauthenticate(wpa_s,
-                                             WLAN_REASON_DEAUTH_LEAVING);
-}
-
-
 /**
  * wpas_dbus_handler_remove_all_networks - Remove all configured networks
  * @message: Pointer to incoming dbus message
@@ -1847,11 +1828,8 @@ static void remove_network(void *arg, struct wpa_ssid *ssid)
 DBusMessage * wpas_dbus_handler_remove_all_networks(
        DBusMessage *message, struct wpa_supplicant *wpa_s)
 {
-       if (wpa_s->sched_scanning)
-               wpa_supplicant_cancel_sched_scan(wpa_s);
-
        /* NB: could check for failure and return an error */
-       wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
+       wpa_supplicant_remove_all_networks(wpa_s);
        return NULL;
 }
 
index 3404f7d01dcb490132f9328ec4f1f339cf799068..01ba032f42c1db47c83d956d46bd1e33b4f4a724 100644 (file)
@@ -4122,6 +4122,52 @@ int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
 }
 
 
+/**
+ * wpa_supplicant_remove_all_networks - Remove all configured networks
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: 0 on success (errors are currently ignored)
+ *
+ * This function performs the following operations:
+ * 1. Remove all networks.
+ * 2. Send network removal notifications.
+ * 3. Update internal state machines.
+ * 4. Stop any running sched scans.
+ */
+int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
+{
+       struct wpa_ssid *ssid;
+
+       if (wpa_s->sched_scanning)
+               wpa_supplicant_cancel_sched_scan(wpa_s);
+
+       eapol_sm_invalidate_cached_session(wpa_s->eapol);
+       if (wpa_s->current_ssid) {
+#ifdef CONFIG_SME
+               wpa_s->sme.prev_bssid_set = 0;
+#endif /* CONFIG_SME */
+               wpa_sm_set_config(wpa_s->wpa, NULL);
+               eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+               if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+                       wpa_s->own_disconnect_req = 1;
+               wpa_supplicant_deauthenticate(
+                       wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+       }
+       ssid = wpa_s->conf->ssid;
+       while (ssid) {
+               struct wpa_ssid *remove_ssid = ssid;
+               int id;
+
+               id = ssid->id;
+               ssid = ssid->next;
+               if (wpa_s->last_ssid == remove_ssid)
+                       wpa_s->last_ssid = NULL;
+               wpas_notify_network_removed(wpa_s, remove_ssid);
+               wpa_config_remove_network(wpa_s->conf, id);
+       }
+       return 0;
+}
+
+
 /**
  * wpa_supplicant_enable_network - Mark a configured network as enabled
  * @wpa_s: wpa_supplicant structure for a network interface
index 2df45c62c662d521dacaae3f0526964489749714..ffaacf94804785a4bf357ebd143aca7c1d61c02d 100644 (file)
@@ -1381,6 +1381,7 @@ void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s);
 
 struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id);
+int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
                                   struct wpa_ssid *ssid);
 void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,