public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ] bap: don't track streams without setup except for ucast server
@ 2025-04-21 16:30 Pauli Virtanen
  2025-04-21 16:30 ` [PATCH BlueZ] shared/bap: fix crash when removing PAC Pauli Virtanen
  2025-04-22  9:11 ` [PATCH BlueZ] bap: don't track streams without setup except for ucast server patchwork-bot+bluetooth
  0 siblings, 2 replies; 4+ messages in thread
From: Pauli Virtanen @ 2025-04-21 16:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen

data->streams is is used for determining which streams can connect to
listening socket. This stream list is specific to ucast server.

Rename the variable to data->server_streams, and only put ucast server
streams there.

Fixes data->streams accumulating dead stream pointers.
---
 profiles/audio/bap.c | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 88d170585..ee7c8bc49 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -106,7 +106,7 @@ struct bap_data {
 	struct queue *snks;
 	struct queue *bcast;
 	struct queue *bcast_snks;
-	struct queue *streams;
+	struct queue *server_streams;
 	GIOChannel *listen_io;
 	unsigned int io_id;
 	int selecting;
@@ -158,7 +158,7 @@ static void bap_data_free(struct bap_data *data)
 	queue_destroy(data->snks, ep_unregister);
 	queue_destroy(data->srcs, ep_unregister);
 	queue_destroy(data->bcast, ep_unregister);
-	queue_destroy(data->streams, NULL);
+	queue_destroy(data->server_streams, NULL);
 	queue_destroy(data->bcast_snks, setup_free);
 	bt_bap_ready_unregister(data->bap, data->ready_id);
 	bt_bap_state_unregister(data->bap, data->state_id);
@@ -1695,7 +1695,7 @@ static void iso_confirm_cb(GIOChannel *io, void *user_data)
 	DBG("ISO: incoming connect from %s (CIG 0x%02x CIS 0x%02x)",
 					address, qos.ucast.cig, qos.ucast.cis);
 
-	stream = queue_remove_if(data->streams, match_stream_qos, &qos);
+	stream = queue_remove_if(data->server_streams, match_stream_qos, &qos);
 	if (!stream) {
 		error("No matching stream found");
 		goto drop;
@@ -2040,6 +2040,12 @@ static void setup_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
 
 	DBG("stream %p", stream);
 
+	if (!data->server_streams)
+		data->server_streams = queue_new();
+
+	if (!queue_find(data->server_streams, NULL, stream))
+		queue_push_tail(data->server_streams, stream);
+
 	/* If IO already set skip creating it again */
 	if (bt_bap_stream_get_io(stream) || data->listen_io)
 		return;
@@ -2143,12 +2149,6 @@ static void setup_create_io(struct bap_data *data, struct bap_setup *setup,
 	DBG("setup %p stream %p defer %s", setup, stream,
 				defer ? "true" : "false");
 
-	if (!data->streams)
-		data->streams = queue_new();
-
-	if (!queue_find(data->streams, NULL, stream))
-		queue_push_tail(data->streams, stream);
-
 	switch (bt_bap_stream_get_type(stream)) {
 	case BT_BAP_STREAM_TYPE_UCAST:
 		setup_create_ucast_io(data, setup, stream, defer);
@@ -2184,7 +2184,7 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
 		if (setup)
 			setup_free(setup);
 		else
-			queue_remove(data->streams, stream);
+			queue_remove(data->server_streams, stream);
 		break;
 	case BT_BAP_STREAM_STATE_CONFIG:
 		if (setup && !setup->id) {
@@ -2365,8 +2365,6 @@ static void bap_state_bcast_src(struct bt_bap_stream *stream, uint8_t old_state,
 		/* Release stream if idle */
 		if (setup)
 			setup_free(setup);
-		else
-			queue_remove(data->streams, stream);
 		break;
 	case BT_BAP_STREAM_STATE_CONFIG:
 		// TO DO Reconfiguration
@@ -2469,8 +2467,6 @@ static void bap_state_bcast_sink(struct bt_bap_stream *stream,
 		/* Release stream if idle */
 		if (setup)
 			setup_free(setup);
-		else
-			queue_remove(data->streams, stream);
 		break;
 	case BT_BAP_STREAM_STATE_CONFIG:
 		if (!setup)
-- 
2.49.0


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

* [PATCH BlueZ] shared/bap: fix crash when removing PAC
  2025-04-21 16:30 [PATCH BlueZ] bap: don't track streams without setup except for ucast server Pauli Virtanen
@ 2025-04-21 16:30 ` Pauli Virtanen
  2025-04-22  9:11   ` patchwork-bot+bluetooth
  2025-04-22  9:11 ` [PATCH BlueZ] bap: don't track streams without setup except for ucast server patchwork-bot+bluetooth
  1 sibling, 1 reply; 4+ messages in thread
From: Pauli Virtanen @ 2025-04-21 16:30 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen

When PAC is removed, streams need to go through RELEASING flow, which in
some cases is not immediate. Access to stream->lpac is UAF during this
time, e.g. in profiles/audio/bap.c:bap_find_setup_by_stream

Allow stream->lpac == NULL. This should occur only if stream is
RELEASING.

When releasing streams due to removed PAC, do RELEASING->IDLE as we
can't cache config then.
---
 src/shared/bap.c | 52 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 42 insertions(+), 10 deletions(-)

diff --git a/src/shared/bap.c b/src/shared/bap.c
index 3a11cb082..4c5b38b1e 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -294,6 +294,7 @@ struct bt_bap_stream {
 	uint8_t state;
 	unsigned int state_id;
 	struct queue *pending_states;
+	bool no_cache_config;
 	bool client;
 	void *user_data;
 };
@@ -1000,6 +1001,9 @@ static void stream_notify_config(struct bt_bap_stream *stream)
 
 	DBG(stream->bap, "stream %p", stream);
 
+	if (!lpac)
+		return;
+
 	len = sizeof(*status) + sizeof(*config) + stream->cc->iov_len;
 	status = malloc(len);
 
@@ -1163,7 +1167,7 @@ static struct bt_bap *bt_bap_ref_safe(struct bt_bap *bap)
 
 static void bap_stream_clear_cfm(struct bt_bap_stream *stream)
 {
-	if (!stream->lpac->ops || !stream->lpac->ops->clear)
+	if (!stream->lpac || !stream->lpac->ops || !stream->lpac->ops->clear)
 		return;
 
 	stream->lpac->ops->clear(stream, stream->lpac->user_data);
@@ -1518,6 +1522,12 @@ static uint8_t stream_config(struct bt_bap_stream *stream, struct iovec *cc,
 
 	DBG(stream->bap, "stream %p", stream);
 
+	if (!pac) {
+		ascs_ase_rsp_add(rsp, stream->ep->id, BT_ASCS_RSP_CONF_REJECTED,
+							BT_ASCS_REASON_CODEC);
+		return 0;
+	}
+
 	/* TODO: Wait for pac->ops response */
 	ascs_ase_rsp_success(rsp, stream->ep->id);
 
@@ -1962,6 +1972,9 @@ static unsigned int bap_bcast_config(struct bt_bap_stream *stream,
 				     struct bt_bap_qos *qos, struct iovec *data,
 				     bt_bap_stream_func_t func, void *user_data)
 {
+	if (!stream->lpac)
+		return 0;
+
 	stream->qos = *qos;
 	stream->lpac->ops->config(stream, stream->cc, &stream->qos,
 			ep_config_cb, stream->lpac->user_data);
@@ -2201,18 +2214,23 @@ static uint8_t stream_release(struct bt_bap_stream *stream, struct iovec *rsp)
 	 * to take action immeditely.
 	 */
 	if (!stream->io) {
+		bool cache_config = !stream->no_cache_config;
+
 		switch (bt_bap_stream_get_state(stream)) {
 		case BT_BAP_STREAM_STATE_CONFIG:
 			/* Released (no caching) */
-			stream_set_state(stream, BT_BAP_STREAM_STATE_RELEASING);
-			stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
+			cache_config = false;
 			break;
 		default:
 			/* Released (caching) */
-			stream_set_state(stream, BT_BAP_STREAM_STATE_RELEASING);
-			stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
 			break;
 		}
+
+		stream_set_state(stream, BT_BAP_STREAM_STATE_RELEASING);
+		if (cache_config)
+			stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
+		else
+			stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
 	} else
 		stream_set_state(stream, BT_BAP_STREAM_STATE_RELEASING);
 
@@ -4214,15 +4232,23 @@ static bool match_stream_lpac(const void *data, const void *user_data)
 	return stream->lpac == pac;
 }
 
-static void remove_streams(void *data, void *user_data)
+static void remove_lpac_streams(void *data, void *user_data)
 {
 	struct bt_bap *bap = data;
 	struct bt_bap_pac *pac = user_data;
 	struct bt_bap_stream *stream;
 
-	stream = queue_remove_if(bap->streams, match_stream_lpac, pac);
-	if (stream)
+	while (1) {
+		stream = queue_remove_if(bap->streams, match_stream_lpac, pac);
+		if (!stream)
+			break;
+
+		bt_bap_stream_ref(stream);
+		stream->no_cache_config = true;
 		bt_bap_stream_release(stream, NULL, NULL);
+		stream->lpac = NULL;
+		bt_bap_stream_unref(stream);
+	}
 }
 
 static void bap_pac_sink_removed(void *data, void *user_data)
@@ -4277,7 +4303,7 @@ bool bt_bap_remove_pac(struct bt_bap_pac *pac)
 	return false;
 
 found:
-	queue_foreach(sessions, remove_streams, pac);
+	queue_foreach(sessions, remove_lpac_streams, pac);
 	queue_foreach(sessions, notify_session_pac_removed, pac);
 	bap_pac_free(pac);
 	return true;
@@ -4998,7 +5024,7 @@ static void bap_stream_config_cfm(struct bt_bap_stream *stream)
 {
 	int err;
 
-	if (!stream->lpac->ops || !stream->lpac->ops->config)
+	if (!stream->lpac || !stream->lpac->ops || !stream->lpac->ops->config)
 		return;
 
 	err = stream->lpac->ops->config(stream, stream->cc, &stream->qos,
@@ -6409,6 +6435,9 @@ bool bt_bap_match_bcast_sink_stream(const void *data, const void *user_data)
 {
 	const struct bt_bap_stream *stream = data;
 
+	if (!stream->lpac)
+		return false;
+
 	return stream->lpac->type == BT_BAP_BCAST_SINK;
 }
 
@@ -6845,6 +6874,9 @@ static void add_new_subgroup(struct bt_base *base,
 	uint16_t cid = 0;
 	uint16_t vid = 0;
 
+	if (!lpac)
+		return;
+
 	bt_bap_pac_get_vendor_codec(lpac, &sgrp->codec.id, &cid,
 			&vid, NULL, NULL);
 	sgrp->codec.cid = cid;
-- 
2.49.0


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

* Re: [PATCH BlueZ] shared/bap: fix crash when removing PAC
  2025-04-21 16:30 ` [PATCH BlueZ] shared/bap: fix crash when removing PAC Pauli Virtanen
@ 2025-04-22  9:11   ` patchwork-bot+bluetooth
  0 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+bluetooth @ 2025-04-22  9:11 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: linux-bluetooth

Hello:

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

On Mon, 21 Apr 2025 19:30:54 +0300 you wrote:
> When PAC is removed, streams need to go through RELEASING flow, which in
> some cases is not immediate. Access to stream->lpac is UAF during this
> time, e.g. in profiles/audio/bap.c:bap_find_setup_by_stream
> 
> Allow stream->lpac == NULL. This should occur only if stream is
> RELEASING.
> 
> [...]

Here is the summary with links:
  - [BlueZ] shared/bap: fix crash when removing PAC
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=578a6fd688b0

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] 4+ messages in thread

* Re: [PATCH BlueZ] bap: don't track streams without setup except for ucast server
  2025-04-21 16:30 [PATCH BlueZ] bap: don't track streams without setup except for ucast server Pauli Virtanen
  2025-04-21 16:30 ` [PATCH BlueZ] shared/bap: fix crash when removing PAC Pauli Virtanen
@ 2025-04-22  9:11 ` patchwork-bot+bluetooth
  1 sibling, 0 replies; 4+ messages in thread
From: patchwork-bot+bluetooth @ 2025-04-22  9:11 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: linux-bluetooth

Hello:

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

On Mon, 21 Apr 2025 19:30:53 +0300 you wrote:
> data->streams is is used for determining which streams can connect to
> listening socket. This stream list is specific to ucast server.
> 
> Rename the variable to data->server_streams, and only put ucast server
> streams there.
> 
> Fixes data->streams accumulating dead stream pointers.
> 
> [...]

Here is the summary with links:
  - [BlueZ] bap: don't track streams without setup except for ucast server
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=d5ef57305b79

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] 4+ messages in thread

end of thread, other threads:[~2025-04-22  9:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-21 16:30 [PATCH BlueZ] bap: don't track streams without setup except for ucast server Pauli Virtanen
2025-04-21 16:30 ` [PATCH BlueZ] shared/bap: fix crash when removing PAC Pauli Virtanen
2025-04-22  9:11   ` patchwork-bot+bluetooth
2025-04-22  9:11 ` [PATCH BlueZ] bap: don't track streams without setup except for ucast server 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