Multiple bss->path in the interface->bss_mapping hash table may be
pointing to the same GSupplicantNetwork structure allocated.
Hence we have to remove all the entries corresponding to the
GSupplicantNetwork which is getting destroyed during network
security change in signal_bss_changed.

This is required to handle the crashes like
/usr/lib/libglib-2.0.so.0.3800.2(g_hash_table_lookup+0x10)
/usr/sbin/connmand(signal_bss_changed+0x64)
/usr/sbin/connmand(g_supplicant_filter+0x98)
/usr/lib/libdbus-1.so.3.7.6(dbus_connection_dispatch+0x334)
/usr/sbin/connmand(message_dispatch+0x10)
/usr/lib/libglib-2.0.so.0.3800.2(g_list_sort_with_data+0x554)
/usr/lib/libglib-2.0.so.0.3800.2(g_main_context_dispatch+0x130)
/usr/lib/libglib-2.0.so.0.3800.2(g_main_context_dispatch+0x4b8)
/usr/lib/libglib-2.0.so.0.3800.2(g_main_loop_run+0x84)
/usr/sbin/connmand(main+0x2b4)
/lib/libc-2.18.so(__libc_start_main+0x114)
/usr/sbin/connmand(_start+0x2c)

---
 gsupplicant/supplicant.c |   30 ++++++++++++++++++++++--------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 37e5e3c..6de3436 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -2438,6 +2438,18 @@ static void signal_network_removed(const char *path, 
DBusMessageIter *iter)
        interface_network_removed(iter, interface);
 }
 
+static void remove_network_entries(gpointer key, gpointer value,
+               gpointer user_data)
+{
+       struct g_supplicant_bss *bss = value;
+       GSupplicantInterface *interface = bss->interface;
+
+       SUPPLICANT_DBG("path is %s", bss->path);
+
+       g_hash_table_remove(bss_mapping, bss->path);
+       g_hash_table_remove(interface->bss_mapping, bss->path);
+}
+
 static void signal_bss_changed(const char *path, DBusMessageIter *iter)
 {
        GSupplicantInterface *interface;
@@ -2487,16 +2499,18 @@ static void signal_bss_changed(const char *path, 
DBusMessageIter *iter)
                memcpy(new_bss, bss, sizeof(struct g_supplicant_bss));
                new_bss->path = g_strdup(bss->path);
 
+               /* Remove entries in hash tables before destroying
+                * GSupplicantNetwork corresponding to network->group
+                */
+               if (g_hash_table_size(network->bss_table) >= 1) {
+                       g_hash_table_foreach(network->bss_table,
+                                       remove_network_entries, network);
+               }
+
                g_hash_table_remove(interface->network_table, network->group);
 
-               if (add_or_replace_bss_to_network(new_bss) < 0) {
-                       /* Remove entries in hash tables to handle the
-                        * failure in add_or_replace_bss_to_network
-                        */
-                       g_hash_table_remove(bss_mapping, path);
-                       g_hash_table_remove(interface->bss_mapping, path);
-                       g_hash_table_remove(network->bss_table, path);
-               }
+               if (add_or_replace_bss_to_network(new_bss) < 0)
+                       SUPPLICANT_DBG("add_or_replace_bss_to_network failed");
 
                return;
        }
-- 
1.7.9.5

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to