From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v6 01/23] shared/gatt-client: Fix calling destroy after unregistering notify
Date: Mon, 28 Sep 2026 16:00:07 -0400 [thread overview]
Message-ID: <20260928200031.1209311-2-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20260928200031.1209311-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
bt_gatt_client_unregister_notify resets the callbacks of the
notification but not its destroy callback, which is called once the
notify_data is freed. If a procedure is still pending at that point,
e.g. the write of the CCC to disable the notifications, it holds a
reference to notify_data so destroy is called later, once the user data
may have been freed, e.g. the reports of HoG:
ERROR: AddressSanitizer: heap-use-after-free
#11 report_notify_destroy profiles/input/hog-lib.c:359
#12 attrib_callbacks_destroy attrib/gattrib.c:130
#13 notify_data_unref src/shared/gatt-client.c:256
#15 destroy_write_op src/shared/gatt-client.c:3189
#16 request_unref src/shared/gatt-client.c:201
#17 destroy_att_send_op src/shared/att.c:215
#18 bt_att_cancel src/shared/att.c:1925
#19 cancel_request src/shared/gatt-client.c:2783
...
#21 bt_gatt_client_cancel_all src/shared/gatt-client.c:2811
#22 bt_gatt_client_free src/shared/gatt-client.c:2290
Call destroy when unregistering instead, once done with notify_data and
holding a reference to the client in case destroy drops the last one.
As destroy is now called when unregistering, reply to StartNotify before
freeing the notify client when enabling the notifications fails, since
it frees the operation the reply is for.
Assisted-by: OpenCode:claude-opus-5.5
---
src/gatt-client.c | 7 +++++--
src/shared/gatt-client.c | 21 +++++++++++++++++++++
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/src/gatt-client.c b/src/gatt-client.c
index 3baf95c4f79c..d94dc9d7fbf6 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
@@ -1488,12 +1488,15 @@ static void register_notify_cb(uint16_t att_ecode, void *user_data)
struct characteristic *chrc = client->chrc;
if (att_ecode) {
+ /* Reply first, as freeing the client unregisters the
+ * notification, which frees op with its destroy callback.
+ */
+ create_notify_reply(op, false, att_ecode);
+
queue_remove(chrc->notify_clients, client);
queue_remove(chrc->service->client->all_notify_clients, client);
notify_client_free(client);
- create_notify_reply(op, false, att_ecode);
-
return;
}
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 92ad7c39c115..b3bc62220e16 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -3842,6 +3842,8 @@ bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
unsigned int id)
{
struct notify_data *notify_data;
+ bt_gatt_client_destroy_func_t destroy;
+ void *user_data;
if (!client || !id)
return false;
@@ -3858,7 +3860,26 @@ bool bt_gatt_client_unregister_notify(struct bt_gatt_client *client,
notify_data->callback = NULL;
notify_data->notify = NULL;
+ /* Call destroy once unregistered, as the user data may be freed then,
+ * while notify_data may still be referenced by a pending procedure,
+ * e.g. the write of the CCC, which would otherwise call it later.
+ */
+ destroy = notify_data->destroy;
+ user_data = notify_data->user_data;
+ notify_data->destroy = NULL;
+
+ /* The client may be freed by destroy, e.g. if the user data holds
+ * its last reference.
+ */
+ bt_gatt_client_ref(client);
+
complete_unregister_notify(notify_data);
+
+ if (destroy)
+ destroy(user_data);
+
+ bt_gatt_client_unref(client);
+
return true;
}
--
2.55.0
next prev parent reply other threads:[~2026-09-28 20:00 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 20:00 [PATCH BlueZ v6 00/23] Add HoG functional tests and shared/hog Luiz Augusto von Dentz
2026-09-28 20:00 ` Luiz Augusto von Dentz [this message]
2026-09-28 22:26 ` bluez.test.bot
2026-09-28 20:00 ` [PATCH BlueZ v6 02/23] client/gatt: Fix setting descriptor value from scripts Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 03/23] client/mgmt: Print Connection Subrate event Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 04/23] emulator: Default to the latest BR/EDR+LE version Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 05/23] client/scripts: Add HoG device scripts Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 06/23] doc: Add functional-hog documentation Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 07/23] test: functional: add HoG tests Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 08/23] test: functional: limit the workers by the memory available Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 09/23] client/agent: Fix crash on Cancel with no pending request Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 10/23] shared/uhid: Fix size of Get Report reply with a Report ID Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 11/23] shared/uhid: Keep reading when an event is not available Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 12/23] shared/tester: Allow expecting a PDU with no response Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 13/23] shared/gatt-client: Fix calling idle callbacks again while notifying Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 14/23] shared/gatt-client: Add bt_gatt_client_is_idle Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 15/23] shared/hog: Add initial implementation Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 16/23] unit/test-hog: Use shared/hog Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 17/23] test: functional: change the HoG SCI mode with the HID Control Point Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 18/23] input/hog: Use shared/hog Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 19/23] doc: Add CONFIG_HIDRAW to the tester kernel config Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 20/23] unit/test-uhid: Add Get Report tests Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 21/23] device: Use bt_att instead of GAttrib Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 22/23] attrib: Remove GAttrib and gatttool Luiz Augusto von Dentz
2026-09-28 20:00 ` [PATCH BlueZ v6 23/23] attrib: Remove directory Luiz Augusto von Dentz
2026-09-29 20:50 ` [PATCH BlueZ v6 00/23] Add HoG functional tests and shared/hog patchwork-bot+bluetooth
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260928200031.1209311-2-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox