If a wifi struct is deallocated during a pending D-Bus method call, wifi_tethering_info may contain a pointer to the freed memory. Reworked the code so that pointers to deallocated wifi structs are cleared. --- plugins/wifi.c | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-)
diff --git a/plugins/wifi.c b/plugins/wifi.c index d18dc6c..ab23bb8 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -128,6 +128,15 @@ struct wifi_data { int servicing; }; +struct wifi_tethering_info { + struct wifi_data *wifi; + struct connman_technology *technology; + char *ifname; + GSupplicantSSID *ssid; +}; + +static GSList *tethering_info_list = NULL; + static GList *iface_list = NULL; static GList *pending_wifi_device = NULL; @@ -671,6 +680,7 @@ static void check_p2p_technology(void) static void wifi_remove(struct connman_device *device) { struct wifi_data *wifi = connman_device_get_data(device); + GSList *t; DBG("device %p wifi %p", device, wifi); @@ -713,6 +723,12 @@ static void wifi_remove(struct connman_device *device) g_free(wifi->autoscan); g_free(wifi->identifier); g_free(wifi); + + for (t = tethering_info_list; t; t = t->next) { + struct wifi_tethering_info *info = t->data; + if (info->wifi == wifi) + info->wifi = NULL; + } } static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len) @@ -2678,13 +2694,6 @@ static void tech_remove(struct connman_technology *technology) wifi_technology = NULL; } -struct wifi_tethering_info { - struct wifi_data *wifi; - struct connman_technology *technology; - char *ifname; - GSupplicantSSID *ssid; -}; - static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase) { GSupplicantSSID *ap; @@ -2719,16 +2728,20 @@ static void ap_start_callback(int result, GSupplicantInterface *interface, struct wifi_tethering_info *info = user_data; DBG("result %d index %d bridge %s", - result, info->wifi->index, info->wifi->bridge); + result, + info->wifi ? info->wifi->index : -1, + info->wifi ? info->wifi->bridge : ""); - if (result < 0) { - connman_inet_remove_from_bridge(info->wifi->index, + if (result < 0 || info->wifi == NULL) { + if (info->wifi) + connman_inet_remove_from_bridge(info->wifi->index, info->wifi->bridge); connman_technology_tethering_notify(info->technology, false); } g_free(info->ifname); g_free(info); + tethering_info_list = g_slist_remove(tethering_info_list, info); } static void ap_create_callback(int result, @@ -2740,14 +2753,16 @@ static void ap_create_callback(int result, DBG("result %d ifname %s", result, g_supplicant_interface_get_ifname(interface)); - if (result < 0) { - connman_inet_remove_from_bridge(info->wifi->index, + if (result < 0 || info->wifi == NULL) { + if (info->wifi) + connman_inet_remove_from_bridge(info->wifi->index, info->wifi->bridge); connman_technology_tethering_notify(info->technology, false); g_free(info->ifname); g_free(info->ssid); g_free(info); + tethering_info_list = g_slist_remove(tethering_info_list, info); return; } @@ -2770,12 +2785,14 @@ static void sta_remove_callback(int result, DBG("ifname %s result %d ", info->ifname, result); - if (result < 0) { - info->wifi->tethering = true; + if (result < 0 || info->wifi == NULL) { + if (info->wifi) + info->wifi->tethering = true; g_free(info->ifname); g_free(info->ssid); g_free(info); + tethering_info_list = g_slist_remove(tethering_info_list, info); return; } @@ -2857,6 +2874,8 @@ static int tech_set_tethering(struct connman_technology *technology, info->wifi->tethering = true; + tethering_info_list = g_slist_prepend(tethering_info_list, info); + err = g_supplicant_interface_remove(interface, sta_remove_callback, info); -- 1.9.1 _______________________________________________ connman mailing list connman@connman.net https://lists.connman.net/mailman/listinfo/connman