gatt: Fix invalid read when disconnecting
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 19 Nov 2018 15:19:39 +0000 (17:19 +0200)
committerhimanshu <h.himanshu@samsung.com>
Tue, 14 Jan 2020 08:53:35 +0000 (14:23 +0530)
In case there is a client of AcquireNotify and a disconnect happens the
code not only have to free the client object but also destroy the io
associated with it, for this reason the client object cannot be freed
until the io is destroyed otherwise it may lead to the following error:

Invalid read of size 4
   at 0x63920: notify_io_destroy (gatt-client.c:1461)
   by 0x63EDB: pipe_io_destroy (gatt-client.c:1082)
   by 0x6405B: characteristic_free (gatt-client.c:1663)
   by 0x81F33: remove_interface (object.c:667)
   by 0x826CB: g_dbus_unregister_interface (object.c:1391)
   by 0x85D2B: queue_remove_all (queue.c:354)
   by 0x635F7: unregister_service (gatt-client.c:1893)
   by 0x85CF7: queue_remove_all (queue.c:339)
   by 0x661DF: btd_gatt_client_service_removed (gatt-client.c:2199)
   by 0x695CB: gatt_service_removed (device.c:3747)
   by 0x85B17: queue_foreach (queue.c:220)
   by 0x91283: notify_service_changed (gatt-db.c:280)
   by 0x91283: gatt_db_service_destroy (gatt-db.c:291)
 Address 0x515ed48 is 0 bytes inside a block of size 20 free'd
   at 0x483EAD0: free (vg_replace_malloc.c:530)
   by 0x85D2B: queue_remove_all (queue.c:354)
   by 0x636D3: unregister_characteristic (gatt-client.c:1741)
   by 0x85D2B: queue_remove_all (queue.c:354)
   by 0x635F7: unregister_service (gatt-client.c:1893)
   by 0x85CF7: queue_remove_all (queue.c:339)
   by 0x661DF: btd_gatt_client_service_removed (gatt-client.c:2199)
   by 0x695CB: gatt_service_removed (device.c:3747)
   by 0x85B17: queue_foreach (queue.c:220)
   by 0x91283: notify_service_changed (gatt-db.c:280)
   by 0x91283: gatt_db_service_destroy (gatt-db.c:291)
   by 0x85D2B: queue_remove_all (queue.c:354)
   by 0x91387: gatt_db_clear_range (gatt-db.c:475)

Change-Id: If5d5159c7fc59f4f3b88afb863eb0b0644ddee09
Signed-off-by: himanshu <h.himanshu@samsung.com>
src/gatt-client.c

index 2b5ef0b..908b3df 100644 (file)
@@ -1874,6 +1874,16 @@ static const GDBusMethodTable characteristic_methods[] = {
        { }
 };
 
+static void remove_client(void *data)
+{
+       struct notify_client *ntfy_client = data;
+       struct btd_gatt_client *client = ntfy_client->chrc->service->client;
+
+       queue_remove(client->all_notify_clients, ntfy_client);
+
+       notify_client_unref(ntfy_client);
+}
+
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
 static const GDBusSignalTable service_signals[] = {
        { GDBUS_SIGNAL("GattServiceAdded",
@@ -1895,7 +1905,6 @@ static void characteristic_free(void *data)
 
        /* List should be empty here */
        queue_destroy(chrc->descs, NULL);
-       queue_destroy(chrc->notify_clients, NULL);
 
        if (chrc->write_io) {
                queue_remove(chrc->service->client->ios, chrc->write_io->io);
@@ -1907,6 +1916,8 @@ static void characteristic_free(void *data)
                sock_io_destroy(chrc->notify_io);
        }
 
+       queue_destroy(chrc->notify_clients, remove_client);
+
        g_free(chrc->path);
        free(chrc);
 }
@@ -1976,16 +1987,6 @@ static struct characteristic *characteristic_create(
        return chrc;
 }
 
-static void remove_client(void *data)
-{
-       struct notify_client *ntfy_client = data;
-       struct btd_gatt_client *client = ntfy_client->chrc->service->client;
-
-       queue_remove(client->all_notify_clients, ntfy_client);
-
-       notify_client_unref(ntfy_client);
-}
-
 static void unregister_characteristic(void *data)
 {
        struct characteristic *chrc = data;
@@ -1999,7 +2000,6 @@ static void unregister_characteristic(void *data)
        if (chrc->write_op)
                bt_gatt_client_cancel(gatt, chrc->write_op->id);
 
-       queue_remove_all(chrc->notify_clients, NULL, NULL, remove_client);
        queue_remove_all(chrc->descs, NULL, NULL, unregister_descriptor);
 
        g_dbus_unregister_interface(btd_get_dbus_connection(), chrc->path,