* [PATCH BlueZ v2 3/4] shared/bap: Don't transition to IDLE inside bap_bcast_set_state
2026-06-29 14:11 [PATCH BlueZ v2 1/4] bass: Fix possible crash on bass_update_bis_sync Luiz Augusto von Dentz
2026-06-29 14:11 ` [PATCH BlueZ v2 2/4] shared/bap: Check if stream is valid before attempting to release Luiz Augusto von Dentz
@ 2026-06-29 14:11 ` Luiz Augusto von Dentz
2026-06-29 14:11 ` [PATCH BlueZ v2 4/4] shared/bap: Use queue_foreach to notify state changes Luiz Augusto von Dentz
2 siblings, 0 replies; 4+ messages in thread
From: Luiz Augusto von Dentz @ 2026-06-29 14:11 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Remove the recursive stream_set_state(IDLE) call from the RELEASING
case in bap_bcast_set_state. This call re-entered bap_bcast_set_state
while the state_cbs queue was still being iterated, causing a
use-after-free if a callback unregistered itself during notification.
---
src/shared/bap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shared/bap.c b/src/shared/bap.c
index 9dd07bc5f2e2..6086924a9cb7 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -2436,7 +2436,6 @@ static void bap_bcast_set_state(struct bt_bap_stream *stream, uint8_t state)
break;
case BT_ASCS_ASE_STATE_RELEASING:
bap_stream_io_detach(stream);
- stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
break;
case BT_ASCS_ASE_STATE_ENABLING:
if (bt_bap_stream_get_io(stream))
@@ -2579,6 +2578,7 @@ static unsigned int bap_bcast_release(struct bt_bap_stream *stream,
void *user_data)
{
stream_set_state(stream, BT_BAP_STREAM_STATE_RELEASING);
+ stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
return 1;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH BlueZ v2 4/4] shared/bap: Use queue_foreach to notify state changes
2026-06-29 14:11 [PATCH BlueZ v2 1/4] bass: Fix possible crash on bass_update_bis_sync Luiz Augusto von Dentz
2026-06-29 14:11 ` [PATCH BlueZ v2 2/4] shared/bap: Check if stream is valid before attempting to release Luiz Augusto von Dentz
2026-06-29 14:11 ` [PATCH BlueZ v2 3/4] shared/bap: Don't transition to IDLE inside bap_bcast_set_state Luiz Augusto von Dentz
@ 2026-06-29 14:11 ` Luiz Augusto von Dentz
2 siblings, 0 replies; 4+ messages in thread
From: Luiz Augusto von Dentz @ 2026-06-29 14:11 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Use queue_foreach to notify state changes since that is considered
safer as it does attempt to detect list modification while traversing
the list.
---
src/shared/bap.c | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/src/shared/bap.c b/src/shared/bap.c
index 6086924a9cb7..7bcf28bcefe4 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -1447,10 +1447,19 @@ static bool bap_stream_io_detach(struct bt_bap_stream *stream)
return true;
}
+static void stream_state_changed(void *data, void *user_data)
+{
+ const struct bt_bap_state *state = data;
+ struct bt_bap_stream *stream = user_data;
+
+ if (state->func)
+ state->func(stream, stream->old_state, stream->state,
+ state->data);
+}
+
static void bap_stream_state_changed(struct bt_bap_stream *stream)
{
struct bt_bap *bap = stream->bap;
- const struct queue_entry *entry;
/* Pre notification updates */
switch (stream->ep->state) {
@@ -1475,14 +1484,13 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
break;
}
- for (entry = queue_get_entries(bap->state_cbs); entry;
- entry = entry->next) {
- struct bt_bap_state *state = entry->data;
+ stream->old_state = stream->ep->old_state;
+ stream->state = stream->ep->state;
- if (state->func)
- state->func(stream, stream->ep->old_state,
- stream->ep->state, state->data);
- }
+ /* Notify callbacks using queue_foreach since it does attempt to
+ * protect against concurrent modifications to the list.
+ */
+ queue_foreach(bap->state_cbs, stream_state_changed, stream);
/* Post notification updates */
switch (stream->ep->state) {
@@ -2407,7 +2415,6 @@ static unsigned int bap_ucast_release(struct bt_bap_stream *stream,
static void bap_bcast_set_state(struct bt_bap_stream *stream, uint8_t state)
{
struct bt_bap *bap = stream->bap;
- const struct queue_entry *entry;
stream->old_state = stream->state;
stream->state = state;
@@ -2419,14 +2426,10 @@ static void bap_bcast_set_state(struct bt_bap_stream *stream, uint8_t state)
bt_bap_stream_statestr(stream->old_state),
bt_bap_stream_statestr(stream->state));
- for (entry = queue_get_entries(bap->state_cbs); entry;
- entry = entry->next) {
- struct bt_bap_state *state = entry->data;
-
- if (state->func)
- state->func(stream, stream->old_state,
- stream->state, state->data);
- }
+ /* Notify callbacks using queue_foreach since it does attempt to
+ * protect against concurrent modifications to the list.
+ */
+ queue_foreach(bap->state_cbs, stream_state_changed, stream);
/* Post notification updates */
switch (stream->state) {
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread