diff mbox series

[BlueZ] gatt-server: Fix crash while disconnecting

Message ID 20220519214002.2525857-1-luiz.dentz@gmail.com
State New
Headers show
Series [BlueZ] gatt-server: Fix crash while disconnecting | expand

Commit Message

Luiz Augusto von Dentz May 19, 2022, 9:40 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

If there is a pending notify multiple the code was not removing before
freeing the object causing the following crash:

Invalid read of size 8
   at 0x4A3D10: notify_multiple (gatt-server.c:1703)
   by 0x4D05F0: timeout_callback (timeout-glib.c:25)
   by 0x4956900: ??? (in /usr/lib64/libglib-2.0.so.0.7000.5)
   by 0x49560AE: g_main_context_dispatch
   (in /usr/lib64/libglib-2.0.so.0.7000.5)
   by 0x49AB307: ??? (in /usr/lib64/libglib-2.0.so.0.7000.5)
   by 0x49557C2: g_main_loop_run
   (in /usr/lib64/libglib-2.0.so.0.7000.5)
   by 0x4D0A34: mainloop_run (mainloop-glib.c:66)
   by 0x4D0F2B: mainloop_run_with_signal (mainloop-notify.c:188)
   by 0x2B0CD1: main (main.c:1276)
 Address 0x6ca35c8 is 136 bytes inside a block of size 144 free'd
   at 0x48470E4: free (vg_replace_malloc.c:872)
   by 0x415E73: gatt_server_cleanup (device.c:698)
   by 0x415E73: attio_cleanup (device.c:715)
   by 0x47745B: queue_foreach (queue.c:207)
   by 0x490C54: disconnect_cb (att.c:701)
   by 0x4CF4AF: watch_callback (io-glib.c:157)
   by 0x49560AE: g_main_context_dispatch
   (in /usr/lib64/libglib-2.0.so.0.7000.5)
   by 0x49AB307: ??? (in /usr/lib64/libglib-2.0.so.0.7000.5)
   by 0x49557C2: g_main_loop_run
   (in /usr/lib64/libglib-2.0.so.0.7000.5)
   by 0x4D0A34: mainloop_run (mainloop-glib.c:66)
   by 0x4D0F2B: mainloop_run_with_signal (mainloop-notify.c:188)
   by 0x2B0CD1: main (main.c:1276)
---
 src/shared/gatt-server.c | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index 2adb4afbf..85cff30ec 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
@@ -121,11 +121,26 @@  struct bt_gatt_server {
 	struct nfy_mult_data *nfy_mult;
 };
 
+static void notify_multiple_free(struct bt_gatt_server *server)
+{
+	if (!server->nfy_mult)
+		return;
+
+	if (server->nfy_mult->id)
+		timeout_remove(server->nfy_mult->id);
+
+	free(server->nfy_mult->pdu);
+	free(server->nfy_mult);
+	server->nfy_mult = NULL;
+}
+
 static void bt_gatt_server_free(struct bt_gatt_server *server)
 {
 	if (server->debug_destroy)
 		server->debug_destroy(server->debug_data);
 
+	notify_multiple_free(server);
+
 	bt_att_unregister(server->att, server->mtu_id);
 	bt_att_unregister(server->att, server->read_by_grp_type_id);
 	bt_att_unregister(server->att, server->read_by_type_id);
@@ -1695,17 +1710,26 @@  bool bt_gatt_server_set_debug(struct bt_gatt_server *server,
 	return true;
 }
 
+static void notify_multiple_timeout_remove(struct bt_gatt_server *server)
+{
+	if (!server->nfy_mult->id)
+		return;
+
+	timeout_remove(server->nfy_mult->id);
+	server->nfy_mult->id = 0;
+}
+
 static bool notify_multiple(void *user_data)
 {
 	struct bt_gatt_server *server = user_data;
 
+	server->nfy_mult->id = 0;
+
 	bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY_MULT,
 			server->nfy_mult->pdu, server->nfy_mult->offset, NULL,
 			NULL, NULL);
 
-	free(server->nfy_mult->pdu);
-	free(server->nfy_mult);
-	server->nfy_mult = NULL;
+	notify_multiple_free(server);
 
 	return false;
 }
@@ -1737,8 +1761,7 @@  bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
 		/* flush buffered data if this request hits buffer size limit */
 		if (data && data->offset > 0 &&
 				data->len - data->offset < 4 + length) {
-			if (server->nfy_mult->id)
-				timeout_remove(server->nfy_mult->id);
+			notify_multiple_timeout_remove(server);
 			notify_multiple(server);
 			/* data has been freed by notify_multiple */
 			data = NULL;