Skip to contentSkip to conversation

Various BAP ucast server/client fixes

PATCH Applied Pauli Virtanen 3 participants 10 messages Aug 8, 2025 – Aug 11, 2025 Bluetooth drivers

lore
Share & tools
lore
#0 lore raw

cover Various BAP ucast server/client fixes

Fix bugs in BAP ucast server associated with stream reconfiguration etc.

Fix misc. bugs BAP ucast client.

Pauli Virtanen (7):
bap: fix multiple release of stream when closing setup
bap: send correct framing value to kernel shared/bap: use correct parser for Config Codec message
media: fix pac_select(), pac_config() return values
media: clear transport if reconfiguring in pac_config()
bap: clear server streams when ucast disconnects shared/bap: check ASE state in find_ep_ucast

 profiles/audio/bap.c   | 16 +++++++++++---
 profiles/audio/media.c | 47 +++++++++++++++++++++++++-----------------
 src/shared/bap.c       | 11 +++++++++-
 3 files changed, 51 insertions(+), 23 deletions(-)
Signature · 1 line
2.50.1
#1 lore raw

PATCH 1/7 bap: fix multiple release of stream when closing setup

If setup->closing, then the stream was already released and should not be released again. Also, if stream is RELEASING on setup_close(), freeing the setup should be delayed until the stream exits that state.

Fixes issue where setup is closed, stream goes RELEASING->CONFIG, the setup is freed and a duplicate release op is queued. Before that completes, the stream is reused for a new setup. In this case, the new setup is incorrectly destroyed when the release op completes although it was intended to destroy the old setup.

---
 profiles/audio/bap.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
profiles/audio/bap.c +8 -3
index 3dc4cd92e..8413a5b38 100644
@@ -856,8 +856,9 @@ static bool release_stream(struct bt_bap_stream *stream)
 
 	switch (bt_bap_stream_get_state(stream)) {
 	case BT_BAP_STREAM_STATE_IDLE:
-	case BT_BAP_STREAM_STATE_RELEASING:
 		return true;
+	case BT_BAP_STREAM_STATE_RELEASING:
+		return false;
 	default:
 		bt_bap_stream_release(stream, NULL, NULL);
 		return false;
@@ -990,6 +991,7 @@ static struct bap_setup *setup_new(struct bap_ep *ep)
 static void setup_free(void *data)
 {
 	struct bap_setup *setup = data;
+	bool closing = setup->closing;
 
 	DBG("%p", setup);
 
@@ -997,7 +999,7 @@ static void setup_free(void *data)
 
 	setup_ready(setup, -ECANCELED, 0);
 
-	if (setup->closing && setup->close_cb)
+	if (closing && setup->close_cb)
 		setup->close_cb(setup, setup->close_cb_data);
 
 	if (setup->stream && setup->id) {
@@ -1019,7 +1021,10 @@ static void setup_free(void *data)
 
 	bt_bap_stream_unlock(setup->stream);
 
-	release_stream(setup->stream);
+	if (!closing) {
+		/* Release if not already done */
+		release_stream(setup->stream);
+	}
 
 	if (setup->ep)
 		bap_update_cigs(setup->ep->data);
Signature · 1 line
2.50.1
#2 lore raw

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/project/bluetooth/list/?series=989501

---Test result---

Test Summary:

CheckPatch                    PENDING   0.28 seconds
GitLint                       PENDING   0.29 seconds
BuildEll                      PASS      20.04 seconds
BluezMake                     PASS      2537.39 seconds
MakeCheck                     PASS      20.49 seconds
MakeDistcheck                 PASS      183.87 seconds
CheckValgrind                 PASS      234.29 seconds
CheckSmatch                   WARNING   304.89 seconds
bluezmakeextell               PASS      128.00 seconds
IncrementalBuild              PENDING   0.25 seconds
ScanBuild                     PASS      905.96 seconds

Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script Output:

##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:

##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
src/shared/bap.c:317:25: warning: array of flexible structuressrc/shared/bap.c: note: in included file:./src/shared/ascs.h:88:25: warning: array of flexible structuressrc/shared/bap.c:317:25: warning: array of flexible structuressrc/shared/bap.c: note: in included file:./src/shared/ascs.h:88:25: warning: array of flexible structuressrc/shared/bap.c:317:25: warning: array of flexible structuressrc/shared/bap.c: note: in included file:./src/shared/ascs.h:88:25: warning: array of flexible structuressrc/shared/bap.c:317:25: warning: array of flexible structuressrc/shared/bap.c: note: in included file:./src/shared/ascs.h:88:25: warning: array of flexible structuressrc/shared/bap.c:317:25: warning: array of flexible structuressrc/shared/bap.c: note: in included file:./src/shared/ascs.h:88:25: warning: array of flexible structuressrc/shared/bap.c:317:25: warning: array of flexible structuressrc/shared/bap.c: note: in included file:./src/shared/ascs.h:88:25: warning: array of flexible structures
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:

---
Regards,
Linux Bluetooth

#3 lore raw

PATCH 2/7 bap: send correct framing value to kernel

In reply to Pauli Virtanen

Get framing value to use from the QoS of the appropriate stream, instead of hardcoding unframed.

---
 profiles/audio/bap.c | 2 ++
 1 file changed, 2 insertions(+)
profiles/audio/bap.c +2 -0
index 8413a5b38..a75919102 100644
@@ -2750,6 +2750,8 @@ static void setup_create_ucast_io(struct bap_data *data,
 						qos[1]->ucast.cig_id;
 	iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id :
 						qos[1]->ucast.cis_id;
+	iso_qos.ucast.framing = qos[0] ? qos[0]->ucast.framing :
+						qos[1]->ucast.framing;
 
 	bap_iso_qos(qos[0], &iso_qos.ucast.in);
 	bap_iso_qos(qos[1], &iso_qos.ucast.out);
Signature · 1 line
2.50.1
#4 lore raw

PATCH 3/7 shared/bap: use correct parser for Config Codec message

In reply to Pauli Virtanen

ASCS Config Codec gets Codec_Specific_Configuration, not Codec_Specific_Capabilities so use the correct parser.

Fixes spurious 'invalid size' printed in debug logs.

---
 src/shared/bap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
src/shared/bap.c +1 -1
index 8c186e6f1..c27e675ff 100644
@@ -3093,7 +3093,7 @@ static uint8_t ep_config(struct bt_bap_endpoint *ep, struct bt_bap *bap,
 	cc.iov_base = util_iov_pull_mem(iov, req->cc_len);
 	cc.iov_len = req->cc_len;
 
-	if (!bt_bap_debug_caps(cc.iov_base, cc.iov_len, bap->debug_func,
+	if (!bt_bap_debug_config(cc.iov_base, cc.iov_len, bap->debug_func,
 						bap->debug_data)) {
 		ascs_ase_rsp_add(rsp, req->ase,
 				BT_ASCS_RSP_CONF_INVALID,
Signature · 1 line
2.50.1
#5 lore raw

PATCH 4/7 media: fix pac_select(), pac_config() return values

In reply to Pauli Virtanen

These return 0 on success, < 0 on error, not TRUE/FALSE.

---
 profiles/audio/media.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)
profiles/audio/media.c +11 -5
index 8e62dca17..a723b311c 100644
@@ -1063,8 +1063,11 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 
 	dbus_message_iter_close_container(&iter, &dict);
 
-	return media_endpoint_async_call(msg, endpoint, NULL, pac_select_cb,
-								data, free);
+	if (!media_endpoint_async_call(msg, endpoint, NULL, pac_select_cb,
+								data, free))
+		return -EIO;
+
+	return 0;
 }
 
 static void pac_cancel_select(struct bt_bap_pac *lpac, bt_bap_pac_select_t cb,
@@ -1228,7 +1231,7 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
 	if (msg == NULL) {
 		error("Couldn't allocate D-Bus message");
 		endpoint_remove_transport(endpoint, transport);
-		return FALSE;
+		return -ENOMEM;
 	}
 
 	data = new0(struct pac_config_data, 1);
@@ -1243,8 +1246,11 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
 
 	g_dbus_get_properties(conn, path, "org.bluez.MediaTransport1", &iter);
 
-	return media_endpoint_async_call(msg, endpoint, transport,
-					pac_config_cb, data, free);
+	if (!media_endpoint_async_call(msg, endpoint, transport,
+						pac_config_cb, data, free))
+		return -EIO;
+
+	return 0;
 }
 
 static void pac_clear(struct bt_bap_stream *stream, void *user_data)
Signature · 1 line
2.50.1
#6 lore raw

PATCH 5/7 media: clear transport if reconfiguring in pac_config()

In reply to Pauli Virtanen

We are not updating transport->configuration if transport already exists in pac_config(), so reconfiguration of a stream leaves sound server with old configuration.

Do this in the same way we do for A2DP: first ClearConfiguration() to remove old transport, then SetConfiguration() to make new one with the new settings.

---
 profiles/audio/media.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)
profiles/audio/media.c +17 -14
index a723b311c..24f191a43 100644
@@ -1208,23 +1208,26 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg,
 	DBG("endpoint %p stream %p", endpoint, stream);
 
 	transport = find_transport(endpoint, stream);
-	if (!transport) {
-		switch (bt_bap_stream_get_type(stream)) {
-		case BT_BAP_STREAM_TYPE_UCAST:
-			transport = pac_ucast_config(stream, cfg, endpoint);
-			break;
-		case BT_BAP_STREAM_TYPE_BCAST:
-			transport = pac_bcast_config(stream, cfg, endpoint);
-			break;
-		}
+	if (transport)
+		clear_configuration(endpoint, transport);
 
-		if (!transport)
-			return -EINVAL;
-
-		endpoint->transports = g_slist_append(endpoint->transports,
-								transport);
+	switch (bt_bap_stream_get_type(stream)) {
+	case BT_BAP_STREAM_TYPE_UCAST:
+		transport = pac_ucast_config(stream, cfg, endpoint);
+		break;
+	case BT_BAP_STREAM_TYPE_BCAST:
+		transport = pac_bcast_config(stream, cfg, endpoint);
+		break;
+	default:
+		transport = NULL;
+		break;
 	}
 
+	if (!transport)
+		return -EINVAL;
+
+	endpoint->transports = g_slist_append(endpoint->transports, transport);
+
 	msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
 						MEDIA_ENDPOINT_INTERFACE,
 						"SetConfiguration");
Signature · 1 line
2.50.1
#7 lore raw

PATCH 6/7 bap: clear server streams when ucast disconnects

In reply to Pauli Virtanen

Streams are freed by bap_detach() without state change callback. Clear data->server_streams explicitly before bap_detach().

Fixes UAF due to stale stream pointers in server_streams.

---
 profiles/audio/bap.c | 3 +++
 1 file changed, 3 insertions(+)
profiles/audio/bap.c +3 -0
index a75919102..c463e6a8a 100644
@@ -3768,6 +3768,9 @@ static int bap_disconnect(struct btd_service *service)
 	queue_remove_all(data->snks, ep_remove, NULL, NULL);
 	queue_remove_all(data->srcs, ep_remove, NULL, NULL);
 
+	queue_destroy(data->server_streams, NULL);
+	data->server_streams = NULL;
+
 	bt_bap_detach(data->bap);
 
 	btd_service_disconnecting_complete(service, 0);
Signature · 1 line
2.50.1
#8 lore raw

PATCH 7/7 shared/bap: check ASE state in find_ep_ucast

In reply to Pauli Virtanen

ASE may be in non-configurable state also if it has no associated stream, eg. as a result of failed stream teardown or other misbehavior. Check also ASE state when selecting a "free" one.

Fixes wrongly picking ASE that is not IDLE/CONFIG/QOS and cannot be configured.

---
 src/shared/bap.c | 9 +++++++++
 1 file changed, 9 insertions(+)
src/shared/bap.c +9 -0
index c27e675ff..ed5c322b4 100644
@@ -6224,6 +6224,15 @@ static bool find_ep_ucast(const void *data, const void *user_data)
 		}
 	}
 
+	switch (ep->state) {
+	case BT_ASCS_ASE_STATE_IDLE:
+	case BT_ASCS_ASE_STATE_CONFIG:
+	case BT_ASCS_ASE_STATE_QOS:
+		break;
+	default:
+		return false;
+	}
+
 	if (ep->dir != match->rpac->type)
 		return false;
 
Signature · 1 line
2.50.1
#9 lore raw
In reply to Pauli Virtanen
This series was applied to bluetooth/bluez.git (master) by Luiz Augusto von Dentz <[email protected]>:

Hello:

This series was applied to bluetooth/bluez.git (master) by Luiz Augusto von Dentz <[email protected]>:

Quoted 13 lines · On Fri, 8 Aug 2025 21:50:32 +0300 you wrote:

Fix bugs in BAP ucast server associated with stream reconfiguration etc.

Fix misc. bugs BAP ucast client.

Pauli Virtanen (7):
bap: fix multiple release of stream when closing setup
bap: send correct framing value to kernel shared/bap: use correct parser for Config Codec message
media: fix pac_select(), pac_config() return values
media: clear transport if reconfiguring in pac_config()
bap: clear server streams when ucast disconnects shared/bap: check ASE state in find_ep_ucast

Quoted 1 line

[...]

Here is the summary with links:
- [BlueZ,1/7] bap: fix multiple release of stream when closing setup

    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=5ab82029d225
  - [BlueZ,2/7] bap: send correct framing value to kernel
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=a98314919a85
  - [BlueZ,3/7] shared/bap: use correct parser for Config Codec message
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=bb0122151d2f
  - [BlueZ,4/7] media: fix pac_select(), pac_config() return values
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=caa495332e4b
  - [BlueZ,5/7] media: clear transport if reconfiguring in pac_config()
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=84c336f2bd7a
  - [BlueZ,6/7] bap: clear server streams when ucast disconnects
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=aba67693b934
  - [BlueZ,7/7] shared/bap: check ASE state in find_ep_ucast
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=5ccbff0898fa

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html