shared/bap: Fix crash on bt_bap_stream_disable
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 23 Oct 2024 14:00:42 +0000 (10:00 -0400)
committerWootak Jung <wootak.jung@samsung.com>
Thu, 20 Feb 2025 07:43:24 +0000 (16:43 +0900)
Calls to bt_bap_stream_disable with unicast stream shall result in
stream_disable if when acting as a server (!stream->client) otherwise it
may lead to the following trace:

bluetoothd[104990]: src/shared/bap.c:bap_queue_req() req 0x555555732470 (op 0x05) queue 0x55555571e850
bluetoothd[104990]: src/gatt-database.c:send_notification_to_device() GATT server sending notification
bluetoothd[104990]: src/shared/bap.c:stream_notify_state() stream 0x55555571b7f0
bluetoothd[104990]: src/shared/bap.c:stream_notify_qos() stream 0x55555571b7f0
bluetoothd[104990]: src/gatt-database.c:send_notification_to_device() GATT server sending notification
bluetoothd[104990]: src/shared/bap.c:bap_process_queue()
bluetoothd[104990]: src/shared/bap.c:bap_send() req 0x555555732470 len 3

Program received signal SIGSEGV, Segmentation fault.
bap_send (bap=bap@entry=0x555555730c50, req=req@entry=0x555555732470) at src/shared/bap.c:1490

Fixes: https://github.com/bluez/bluez/issues/991
Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
src/shared/bap.c

index 00c3b9ff6a1b5c3dec0c01bb951fcae0ec488777..8d04290f88ae2e88a804205fde79c86d1b6d4784 100644 (file)
@@ -1872,6 +1872,27 @@ static unsigned int bap_ucast_start(struct bt_bap_stream *stream,
        return req->id;
 }
 
+static uint8_t stream_disable(struct bt_bap_stream *stream, struct iovec *rsp)
+{
+       if (!stream || stream->ep->state == BT_BAP_STREAM_STATE_QOS ||
+                       stream->ep->state == BT_BAP_STREAM_STATE_IDLE)
+               return 0;
+
+       DBG(stream->bap, "stream %p", stream);
+
+       ascs_ase_rsp_success(rsp, stream->ep->id);
+
+       /* Sink can autonomously transit to QOS while source needs to go to
+        * Disabling until BT_ASCS_STOP is received.
+        */
+       if (stream->ep->dir == BT_BAP_SINK)
+               stream_set_state(stream, BT_BAP_STREAM_STATE_QOS);
+       else
+               stream_set_state(stream, BT_BAP_STREAM_STATE_DISABLING);
+
+       return 0;
+}
+
 static unsigned int bap_ucast_disable(struct bt_bap_stream *stream,
                                        bool disable_links,
                                        bt_bap_stream_func_t func,
@@ -1881,6 +1902,9 @@ static unsigned int bap_ucast_disable(struct bt_bap_stream *stream,
        struct bt_ascs_disable disable;
        struct bt_bap_req *req;
 
+       if (!stream->client)
+               return stream_disable(stream, NULL);
+
        memset(&disable, 0, sizeof(disable));
 
        disable.ase = stream->ep->id;
@@ -2790,27 +2814,6 @@ static uint8_t ascs_start(struct bt_ascs *ascs, struct bt_bap *bap,
        return ep_start(ep, rsp);
 }
 
-static uint8_t stream_disable(struct bt_bap_stream *stream, struct iovec *rsp)
-{
-       if (!stream || stream->ep->state == BT_BAP_STREAM_STATE_QOS ||
-                       stream->ep->state == BT_BAP_STREAM_STATE_IDLE)
-               return 0;
-
-       DBG(stream->bap, "stream %p", stream);
-
-       ascs_ase_rsp_success(rsp, stream->ep->id);
-
-       /* Sink can autonomously transit to QOS while source needs to go to
-        * Disabling until BT_ASCS_STOP is received.
-        */
-       if (stream->ep->dir == BT_BAP_SINK)
-               stream_set_state(stream, BT_BAP_STREAM_STATE_QOS);
-       else
-               stream_set_state(stream, BT_BAP_STREAM_STATE_DISABLING);
-
-       return 0;
-}
-
 static uint8_t ep_disable(struct bt_bap_endpoint *ep, struct iovec *rsp)
 {
        struct bt_bap_stream *stream = ep->stream;