[PATCH] shared/gatt-client: Fix notify_list corruption

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When gatt-client processes service changed indication,
notify_list is modified in its foreach callback.

This makes queue_foreach's "next" point to freed memory area and process
crash.

This patch adds service changed indication to queue.
After notify_list's foreach is done, queued one is processed smoothly.

Invalid read of size 4
   at 0x8056B91: queue_foreach (queue.c:219)
   by 0x8051F44: notify_cb (gatt-client.c:1633)
   by 0x804E1A9: can_read_data (att.c:800)
   by 0x80558E1: io_callback (io-mainloop.c:123)
   by 0x8056505: mainloop_run (mainloop.c:157)
   by 0x804995E: main (btgatt-client.c:1664)
 Address 0x41a3784 is 4 bytes inside a block of size 8 free'd
   at 0x402750C: free (vg_replace_malloc.c:427)
   by 0x8056D2F: queue_remove_if (queue.c:302)
   by 0x8056DD0: queue_remove_all (queue.c:331)
   by 0x804F61E: process_service_changed (gatt-client.c:332)
   by 0x804E7F1: notify_handler (gatt-client.c:1617)
   by 0x8056B9E: queue_foreach (queue.c:220)
   by 0x8051F44: notify_cb (gatt-client.c:1633)
   by 0x804E1A9: can_read_data (att.c:800)
   by 0x80558E1: io_callback (io-mainloop.c:123)
   by 0x8056505: mainloop_run (mainloop.c:157)
   by 0x804995E: main (btgatt-client.c:1664)
---
 src/shared/gatt-client.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 06ac763..95304ca 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -1469,11 +1469,6 @@ static void service_changed_cb(uint16_t value_handle, const uint8_t *value,
 			"Service Changed received - start: 0x%04x end: 0x%04x",
 			start, end);
 
-	if (!client->in_svc_chngd) {
-		process_service_changed(client, start, end);
-		return;
-	}
-
 	op = new0(struct service_changed_op, 1);
 
 	op->start_handle = start;
@@ -1623,6 +1618,7 @@ static void notify_cb(uint8_t opcode, const void *pdu, uint16_t length,
 {
 	struct bt_gatt_client *client = user_data;
 	struct pdu_data pdu_data;
+	struct service_changed_op *sc_op;
 
 	bt_gatt_client_ref(client);
 
@@ -1632,6 +1628,13 @@ static void notify_cb(uint8_t opcode, const void *pdu, uint16_t length,
 
 	queue_foreach(client->notify_list, notify_handler, &pdu_data);
 
+	if (client->in_svc_chngd == false &&
+	    (sc_op = queue_pop_head(client->svc_chngd_queue))) {
+		process_service_changed(client, sc_op->start_handle,
+						sc_op->end_handle);
+		free(sc_op);
+	}
+
 	if (opcode == BT_ATT_OP_HANDLE_VAL_IND)
 		bt_att_send(client->att, BT_ATT_OP_HANDLE_VAL_CONF, NULL, 0,
 							NULL, NULL, NULL);
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux