Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ 1/2] shared/mgmt: Fix notify leak in mgmt_unregister()
@ 2026-10-08  3:41 Iaroslav Voitovych
  2026-10-08  3:41 ` [PATCH BlueZ 2/2] unit/test-mgmt: Test unregistering from callbacks Iaroslav Voitovych
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Iaroslav Voitovych @ 2026-10-08  3:41 UTC (permalink / raw)
  To: linux-bluetooth

mgmt_unregister() called from a notification callback takes the entry
off notify_list and marks it removed instead of freeing it.
process_notify() frees the removed entries still on notify_list once
the walk is done, so this one is never freed and its destroy callback
never runs.

If the callback unregisters the next entry rather than its own, this
is also a use-after-free: queue_foreach() has already saved that
entry's queue node, and queue_remove_if() frees it. That is the crash
fixed for mgmt_unregister_index() by commit 872729a91632
("shared/mgmt: Fix crash when removing index"), still present in
mgmt_unregister().

Leave the entry on the list while notifying, as mgmt_unregister_index()
and mgmt_unregister_all() do, and let process_notify() free it.
Unregistering an entry that is already marked removed now returns
false, since it is no longer registered; for an entry marked by
mgmt_unregister_index() or mgmt_unregister_all(), mgmt_unregister()
used to return true, take it off the list and leak it. No caller
checks the return value.

mgmt-tester, mesh-tester and userchan-tester unregister from event
callbacks, and under ASan each reports these entries as leaked, for
example userchan-tester:

  Direct leak of 80 byte(s) in 2 object(s) allocated from:
    #0 in malloc
    #1 in util_malloc src/shared/util.c:46
    #2 in mgmt_register src/shared/mgmt.c:974
    #3 in test_open_success tools/userchan-tester.c:275

Fixes: 872729a91632 ("shared/mgmt: Fix crash when removing index")
---
 src/shared/mgmt.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/shared/mgmt.c b/src/shared/mgmt.c
index f56bcee14..f5aeecf3f 100644
--- a/src/shared/mgmt.c
+++ b/src/shared/mgmt.c
@@ -999,18 +999,28 @@ bool mgmt_unregister(struct mgmt *mgmt, unsigned int id)
 	if (!mgmt || !id)
 		return false;
 
-	notify = queue_remove_if(mgmt->notify_list, match_notify_id,
+	/*
+	 * While notifying, leave the entry on the list for process_notify()
+	 * to free once it is done with it.
+	 */
+	if (mgmt->in_notify) {
+		notify = queue_find(mgmt->notify_list, match_notify_id,
 							UINT_TO_PTR(id));
-	if (!notify)
-		return false;
+		if (!notify || notify->removed)
+			return false;
+
+		notify->removed = true;
+		mgmt->need_notify_cleanup = true;
 
-	if (!mgmt->in_notify) {
-		destroy_notify(notify);
 		return true;
 	}
 
-	notify->removed = true;
-	mgmt->need_notify_cleanup = true;
+	notify = queue_remove_if(mgmt->notify_list, match_notify_id,
+							UINT_TO_PTR(id));
+	if (!notify)
+		return false;
+
+	destroy_notify(notify);
 
 	return true;
 }

base-commit: d84171e6cd68a5ab95d0f3a384279c36bd108a13
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-08 15:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-08  3:41 [PATCH BlueZ 1/2] shared/mgmt: Fix notify leak in mgmt_unregister() Iaroslav Voitovych
2026-10-08  3:41 ` [PATCH BlueZ 2/2] unit/test-mgmt: Test unregistering from callbacks Iaroslav Voitovych
2026-10-08 10:41 ` [BlueZ,1/2] shared/mgmt: Fix notify leak in mgmt_unregister() bluez.test.bot
2026-10-08 15:20 ` [PATCH BlueZ 1/2] " patchwork-bot+bluetooth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox