All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration
@ 2026-10-01 14:34 Eduardo Alves
  2026-10-01 14:34 ` [PATCH BlueZ 1/2] a2dp: Fix UAF after rejected SetConfiguration Eduardo Alves
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Eduardo Alves @ 2026-10-01 14:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eduardo Alves

bluetoothd 5.87 segfaulted in auto_config() with a G06-BT headset while
WirePlumber 0.5.17 was stuck and its SetConfiguration calls ended in
NoReply: the AVDTP channel went away while the reply was pending, and
the reply then ran auto_config() with a NULL session.

Patch 2 fixes that crash and removes the MediaTransport created for the
aborted request, so the next connection works. Patch 1 is an older,
independent bug found while testing it: a rejected SetConfiguration
leaves a dangling a2dp_stream on sep->streams, which ASAN reports as a
use-after-free once the stream is configured again on the same session.

Both were reproduced with test-functional (two VMs over btvirt, ASAN)
using a MediaEndpoint1 that delays, never sends or rejects its
SetConfiguration reply; master fails all three cases, the series passes
them. The reproducer test is available if you want it.

Eduardo Alves (2):
  a2dp: Fix UAF after rejected SetConfiguration
  a2dp: Fix crash on NULL session in auto_config

 profiles/audio/a2dp.c  | 39 ++++++++++++++++++++++++++++++++++++++-
 profiles/audio/media.c | 10 ++++++++++
 2 files changed, 48 insertions(+), 1 deletion(-)

-- 
2.56.0


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

* [PATCH BlueZ 1/2] a2dp: Fix UAF after rejected SetConfiguration
  2026-10-01 14:34 [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration Eduardo Alves
@ 2026-10-01 14:34 ` Eduardo Alves
  2026-10-01 16:48   ` a2dp: Fix crashes around pending SetConfiguration bluez.test.bot
  2026-10-01 14:34 ` [PATCH BlueZ 2/2] a2dp: Fix crash on NULL session in auto_config Eduardo Alves
  2026-10-08 15:00 ` [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration patchwork-bot+bluetooth
  2 siblings, 1 reply; 5+ messages in thread
From: Eduardo Alves @ 2026-10-01 14:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eduardo Alves

When the MediaEndpoint1 rejects SetConfiguration, auto_config() calls
setconf_cb() with an error and avdtp frees the avdtp_stream, but the
a2dp_stream wrapping it is left on sep->streams with a dangling stream
pointer. The next stream configured on the same session finds it in
a2dp_config() and reads the freed avdtp_stream:

  ERROR: AddressSanitizer: heap-use-after-free
  READ of size 4
    #0 avdtp_stream_get_state profiles/audio/avdtp.c:3952
    #1 a2dp_config profiles/audio/a2dp.c:3282
    #2 select_complete profiles/audio/source.c:200
    #3 finalize_select profiles/audio/a2dp.c:486
  freed by thread T0 here:
    #1 stream_free profiles/audio/avdtp.c:747
    #2 setconf_cb profiles/audio/avdtp.c:1504
    #3 auto_config profiles/audio/a2dp.c:752
    #4 endpoint_setconf_cb profiles/audio/a2dp.c:768

Fix it by destroying the a2dp_stream when the configuration is
rejected, which also drops the session reference it holds.

This can be reproduced with test-functional using two VMs over btvirt,
where the A2DP Sink endpoint replies to SetConfiguration with an error
and the sink then connects to the source on the same session.

Assisted-by: Claude:claude-opus-5-5
---
 profiles/audio/a2dp.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index efbe73f1b..e4b6f03fe 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -748,9 +748,17 @@ static gboolean auto_config(gpointer data)
 	}
 
 done:
-	if (setup->setconf_cb)
+	if (setup->setconf_cb) {
+		/* Rejecting the configuration frees the avdtp_stream */
+		if (setup->err)
+			a2dp_stream_destroy(setup->sep, setup->stream);
+
 		setup->setconf_cb(setup->session, setup->stream, setup->err);
 
+		if (setup->err)
+			setup->stream = NULL;
+	}
+
 	finalize_config(setup);
 
 	setup_error_set(setup, NULL);
-- 
2.56.0


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

* [PATCH BlueZ 2/2] a2dp: Fix crash on NULL session in auto_config
  2026-10-01 14:34 [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration Eduardo Alves
  2026-10-01 14:34 ` [PATCH BlueZ 1/2] a2dp: Fix UAF after rejected SetConfiguration Eduardo Alves
@ 2026-10-01 14:34 ` Eduardo Alves
  2026-10-08 15:00 ` [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration patchwork-bot+bluetooth
  2 siblings, 0 replies; 5+ messages in thread
From: Eduardo Alves @ 2026-10-01 14:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Eduardo Alves

If the AVDTP channel is disconnected while bluetoothd is still waiting
for the MediaEndpoint1 to reply to SetConfiguration, channel_free()
sets setup->session to NULL but the setup stays alive since the pending
endpoint request holds a reference to it. Once the endpoint replies, or
the call times out and the request is canceled, endpoint_setconf_cb()
calls auto_config() which passes the NULL session to avdtp_get_device()
and then dereferences the resulting NULL device:

  bluetoothd[820]: profiles/audio/media.c:endpoint_reply() Endpoint
    replied with an error: org.freedesktop.DBus.Error.NoReply
  kernel: bluetoothd[820]: segfault at 1a0 ip 00005633dd741323
    sp 00007ffe51923650 error 4 in bluetoothd

  #0  auto_config (data=0x56340361a120) at profiles/audio/a2dp.c:723
  #1  endpoint_setconf_cb (setup=...) at profiles/audio/a2dp.c:768
  #2  media_endpoint_cancel (request=...) at profiles/audio/media.c:208
  #3  media_endpoint_cancel_all () at profiles/audio/media.c:216
  #4  clear_endpoint () at profiles/audio/media.c:379
  #5  endpoint_reply (user_data=...) at profiles/audio/media.c:407

  (gdb) p *setup
  $1 = {chan = 0x0, session = 0x0, ...,
        setconf_cb = 0x5633dd74c780 <setconf_cb>, ..., ref = 2}

Commit 14750a2e48f4 ("audio/a2dp: Fix Access session device only when
its valid") fixed the same crash, but commit 77932f2dac1a
("profiles/audio: add nullity checks") moved avdtp_get_device() back
ahead of the checks. Just reordering is not enough though: the
a2dp_stream is still on sep->streams, so the aborted check passes and
setconf_cb() would then be called with a NULL session as well.

Fix it by rejecting the pending Set Configuration in channel_free()
while the session is still valid, which also frees the pending
avdtp_stream and the a2dp_stream, both previously leaked together with
the session reference held by the latter, and by making auto_config()
bail out when setup->session is NULL, releasing its setup reference.
setconf_cb is cleared once called so it cannot be called twice.

channel_free() also clears the endpoint configuration, which sends
ClearConfiguration and removes the MediaTransport created for the
request. Otherwise a late successful reply leaves the transport
registered and the next connection fails with "Resource temporarily
unavailable". Since the transport may now be freed while the request
is pending, endpoint_remove_transport() resets the transport of the
pending requests so a late error reply does not free it twice.

The crash can be reproduced with test-functional using two VMs over
btvirt, where the A2DP Sink endpoint delays or never sends its
SetConfiguration reply and the A2DP Source disconnects meanwhile.

Assisted-by: Claude:claude-opus-5-5
---
 profiles/audio/a2dp.c  | 29 +++++++++++++++++++++++++++++
 profiles/audio/media.c | 10 ++++++++++
 2 files changed, 39 insertions(+)

diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index e4b6f03fe..be6dc4b99 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -718,6 +718,13 @@ static gboolean auto_config(gpointer data)
 	struct btd_service *service;
 	struct a2dp_stream *stream;
 
+	/* Check if the channel has been disconnected while waiting for the
+	 * endpoint, in which case channel_free has already rejected the
+	 * configuration.
+	 */
+	if (!setup->session)
+		goto done;
+
 	dev = avdtp_get_device(setup->session);
 
 	if (setup->sep->type == AVDTP_SEP_TYPE_SOURCE)
@@ -754,6 +761,7 @@ done:
 			a2dp_stream_destroy(setup->sep, setup->stream);
 
 		setup->setconf_cb(setup->session, setup->stream, setup->err);
+		setup->setconf_cb = NULL;
 
 		if (setup->err)
 			setup->stream = NULL;
@@ -1932,6 +1940,27 @@ static void channel_free(void *data)
 		setup_ref(setup);
 		/* Finalize pending commands before we NULL setup->session */
 		finalize_setup_errno(setup, -ENOTCONN, finalize_all, NULL);
+		/* Reject pending Set Configuration since the endpoint reply
+		 * can no longer be processed without setup->session.
+		 */
+		if (setup->setconf_cb) {
+			struct a2dp_sep *sep = setup->sep;
+			struct avdtp_error err;
+
+			avdtp_error_init(&err, AVDTP_MEDIA_CODEC,
+					AVDTP_UNSUPPORTED_CONFIGURATION);
+			a2dp_stream_destroy(sep, setup->stream);
+			setup->setconf_cb(setup->session, setup->stream, &err);
+			setup->setconf_cb = NULL;
+			setup->stream = NULL;
+			/* Clear the transport set while waiting for the
+			 * endpoint so it can be configured again.
+			 */
+			if (sep->endpoint && sep->endpoint->clear_configuration)
+				sep->endpoint->clear_configuration(sep,
+					avdtp_get_device(setup->session),
+					sep->user_data);
+		}
 		avdtp_unref(setup->session);
 		setup->session = NULL;
 		setup_unref(setup);
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index dd1d4e571..d616034cb 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -353,9 +353,19 @@ static struct media_adapter *find_adapter(struct btd_device *device)
 static void endpoint_remove_transport(struct media_endpoint *endpoint,
 					struct media_transport *transport)
 {
+	GSList *l;
+
 	if (!endpoint || !transport)
 		return;
 
+	/* Pending requests must not refer to the transport once freed */
+	for (l = endpoint->requests; l; l = l->next) {
+		struct endpoint_request *request = l->data;
+
+		if (request->transport == transport)
+			request->transport = NULL;
+	}
+
 	endpoint->transports = g_slist_remove(endpoint->transports, transport);
 	media_transport_destroy(transport);
 }
-- 
2.56.0


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

* RE: a2dp: Fix crashes around pending SetConfiguration
  2026-10-01 14:34 ` [PATCH BlueZ 1/2] a2dp: Fix UAF after rejected SetConfiguration Eduardo Alves
@ 2026-10-01 16:48   ` bluez.test.bot
  0 siblings, 0 replies; 5+ messages in thread
From: bluez.test.bot @ 2026-10-01 16:48 UTC (permalink / raw)
  To: linux-bluetooth, eduardoalves8006

[-- Attachment #1: Type: text/plain, Size: 1021 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1177732/

---Test result---

Test Summary:
CheckPatch                    PASS      0.83 seconds
GitLint                       PASS      0.53 seconds
BuildEll                      PASS      19.12 seconds
BluezMake                     PASS      370.55 seconds
MakeCheck                     PASS      3.46 seconds
MakeDistcheck                 PASS      138.68 seconds
CheckValgrind                 PASS      148.29 seconds
CheckSmatch                   PASS      286.00 seconds
bluezmakeextell               PASS      92.75 seconds
TestFunctional                PASS      1105.32 seconds
IncrementalBuild              PASS      382.22 seconds
ScanBuild                     PASS      1102.19 seconds



https://github.com/bluez/bluez/pull/2618

---
Regards,
Linux Bluetooth


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

* Re: [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration
  2026-10-01 14:34 [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration Eduardo Alves
  2026-10-01 14:34 ` [PATCH BlueZ 1/2] a2dp: Fix UAF after rejected SetConfiguration Eduardo Alves
  2026-10-01 14:34 ` [PATCH BlueZ 2/2] a2dp: Fix crash on NULL session in auto_config Eduardo Alves
@ 2026-10-08 15:00 ` patchwork-bot+bluetooth
  2 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+bluetooth @ 2026-10-08 15:00 UTC (permalink / raw)
  To: Eduardo Alves; +Cc: linux-bluetooth

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Thu,  1 Oct 2026 10:34:34 -0400 you wrote:
> bluetoothd 5.87 segfaulted in auto_config() with a G06-BT headset while
> WirePlumber 0.5.17 was stuck and its SetConfiguration calls ended in
> NoReply: the AVDTP channel went away while the reply was pending, and
> the reply then ran auto_config() with a NULL session.
> 
> Patch 2 fixes that crash and removes the MediaTransport created for the
> aborted request, so the next connection works. Patch 1 is an older,
> independent bug found while testing it: a rejected SetConfiguration
> leaves a dangling a2dp_stream on sep->streams, which ASAN reports as a
> use-after-free once the stream is configured again on the same session.
> 
> [...]

Here is the summary with links:
  - [BlueZ,1/2] a2dp: Fix UAF after rejected SetConfiguration
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=ef54133c69e9
  - [BlueZ,2/2] a2dp: Fix crash on NULL session in auto_config
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

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

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-01 14:34 [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration Eduardo Alves
2026-10-01 14:34 ` [PATCH BlueZ 1/2] a2dp: Fix UAF after rejected SetConfiguration Eduardo Alves
2026-10-01 16:48   ` a2dp: Fix crashes around pending SetConfiguration bluez.test.bot
2026-10-01 14:34 ` [PATCH BlueZ 2/2] a2dp: Fix crash on NULL session in auto_config Eduardo Alves
2026-10-08 15:00 ` [PATCH BlueZ 0/2] a2dp: Fix crashes around pending SetConfiguration patchwork-bot+bluetooth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.