If there are pending D-Bus calls made inside supplicant code when
wifi_remove() frees the wifi struct, wifi plugin callback functions
may attempt to use already released memory when the calls complete.

Fixed by cancelling any outstanding supplicant calls in wifi_remove().
---
 gsupplicant/gsupplicant.h |  2 ++
 gsupplicant/supplicant.c  | 15 +++++++++------
 plugins/wifi.c            |  2 ++
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
index a5ec405..7a3c843 100644
--- a/gsupplicant/gsupplicant.h
+++ b/gsupplicant/gsupplicant.h
@@ -172,6 +172,8 @@ typedef void (*GSupplicantInterfaceCallback) (int result,
                                        GSupplicantInterface *interface,
                                                        void *user_data);
 
+void g_supplicant_interface_cancel(GSupplicantInterface *interface);
+
 int g_supplicant_interface_create(const char *ifname, const char *driver,
                                        const char *bridge,
                                        GSupplicantInterfaceCallback callback,
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 7b0f4d4..ea68433 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -1990,9 +1990,7 @@ static void interface_removed(DBusMessageIter *iter, void 
*user_data)
                return;
 
        interface = g_hash_table_lookup(interface_table, path);
-       SUPPLICANT_DBG("Cancelling any pending DBus calls");
-       supplicant_dbus_method_call_cancel_all(interface);
-       supplicant_dbus_property_call_cancel_all(interface);
+       g_supplicant_interface_cancel(interface);
 
        g_hash_table_remove(interface_table, path);
 }
@@ -2582,6 +2580,13 @@ static DBusHandlerResult 
g_supplicant_filter(DBusConnection *conn,
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
+void g_supplicant_interface_cancel(GSupplicantInterface *interface)
+{
+       SUPPLICANT_DBG("Cancelling any pending DBus calls");
+       supplicant_dbus_method_call_cancel_all(interface);
+       supplicant_dbus_property_call_cancel_all(interface);
+}
+
 struct supplicant_regdom {
        GSupplicantCountryCallback callback;
        const char *alpha2;
@@ -2980,9 +2985,7 @@ int g_supplicant_interface_remove(GSupplicantInterface 
*interface,
        if (!system_available)
                return -EFAULT;
 
-       SUPPLICANT_DBG("Cancelling any pending DBus calls");
-       supplicant_dbus_method_call_cancel_all(interface);
-       supplicant_dbus_property_call_cancel_all(interface);
+       g_supplicant_interface_cancel(interface);
 
        data = dbus_malloc0(sizeof(*data));
        if (!data)
diff --git a/plugins/wifi.c b/plugins/wifi.c
index ef4dd95..aaa5b00 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -313,6 +313,8 @@ static void wifi_remove(struct connman_device *device)
 
        g_supplicant_interface_set_data(wifi->interface, NULL);
 
+       g_supplicant_interface_cancel(wifi->interface);
+
        if (wifi->scan_params)
                g_supplicant_free_scan_params(wifi->scan_params);
 
-- 
1.8.5.3

_______________________________________________
connman mailing list
connman@connman.net
https://lists.connman.net/mailman/listinfo/connman

Reply via email to