Message ID | 20231004075646.4277-2-silviu.barbulescu@nxp.com |
---|---|
State | Superseded |
Headers | show |
Series | Update transport acquire/release flow BAP bcast source | expand |
Hi Silviu, this patch introduced a use-after-free, reproducer: - connect to a2dp sink - start playing - pause and wait until stream suspends - bluetoothd crashes in a2dp_suspend_complete() Here's the output running with address sanitizer: bluetoothd[181120]: profiles/audio/a2dp.c:suspend_cfm() Source 0x60600001e500: Suspend_Cfm ================================================================= ==181120==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300005a730 at pc 0xaaaaf9dbeea8 bp 0xfffff4d3b690 sp 0xfffff4d3b6a8 READ of size 8 at 0x60300005a730 thread T0 #0 0xaaaaf9dbeea4 in a2dp_suspend_complete profiles/audio/transport.c:426 #1 0xaaaaf9d7d37c in finalize_suspend profiles/audio/a2dp.c:376 #2 0xaaaaf9d7e060 in suspend_cfm profiles/audio/a2dp.c:1276 #3 0xaaaaf9da0ddc in avdtp_delay_report_resp profiles/audio/avdtp.c:2928 #4 0xaaaaf9da0ddc in avdtp_parse_resp profiles/audio/avdtp.c:2997 #5 0xaaaaf9da0ddc in session_cb profiles/audio/avdtp.c:2286 #6 0xffff6e77030c in g_main_dispatch ../glib/gmain.c:3476 #7 0xffff6e77030c in g_main_context_dispatch_unlocked ../glib/gmain.c:4284 #8 0xffff6e7ce598 in g_main_context_iterate_unlocked.isra.0 ../glib/gmain.c:4349 #9 0xffff6e771a60 in g_main_loop_run (/lib64/libglib-2.0.so.0+0x61a60) (BuildId: 7d17ee836a99abf35136ebb46126a95dee66511a) #10 0xaaaafa0ad0d8 in mainloop_run src/shared/mainloop-glib.c:66 #11 0xaaaafa0ad920 in mainloop_run_with_signal src/shared/mainloop-notify.c:188 #12 0xaaaaf9d5489c in main src/main.c:1452 #13 0xffff6dd209d8 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #14 0xffff6dd20aac in __libc_start_main_impl ../csu/libc-start.c:360 #15 0xaaaaf9d5686c in _start (/home/jonas/git/bluez/src/bluetoothd+0x55686c) (BuildId: 8922b026a55aac729ed13de54b3a622a31b5bb2b) 0x60300005a730 is located 0 bytes inside of 32-byte region [0x60300005a730,0x60300005a750) freed by thread T0 here: #0 0xffff6ea24638 in __interceptor_free.part.0 (/lib64/libasan.so.8+0xc4638) (BuildId: a77e9fa1e1448d41e9a8ddaf28aa5612f3ffc397) #1 0xffff6e773114 in g_free (/lib64/libglib-2.0.so.0+0x63114) (BuildId: 7d17ee836a99abf35136ebb46126a95dee66511a) #2 0xaaaaf9dbc42c in media_transport_remove_owner profiles/audio/transport.c:322 #3 0xaaaaf9dc0b64 in bap_disable_complete profiles/audio/transport.c:632 #4 0xaaaaf9dc0b64 in release profiles/audio/transport.c:674 #5 0xaaaaf9ff2574 in process_message gdbus/object.c:246 #6 0xffff6e69de78 in _dbus_object_tree_dispatch_and_unlock ../../dbus/dbus-object-tree.c:1021 #7 0xaaaaf9fe44a4 in message_dispatch gdbus/mainloop.c:59 #8 0xffff6e76c444 in g_idle_dispatch ../glib/gmain.c:6282 #9 0xffff6e77030c in g_main_dispatch ../glib/gmain.c:3476 #10 0xffff6e77030c in g_main_context_dispatch_unlocked ../glib/gmain.c:4284 #11 0xffff6e7ce598 in g_main_context_iterate_unlocked.isra.0 ../glib/gmain.c:4349 #12 0xffff6e771a60 in g_main_loop_run (/lib64/libglib-2.0.so.0+0x61a60) (BuildId: 7d17ee836a99abf35136ebb46126a95dee66511a) #13 0xaaaafa0ad0d8 in mainloop_run src/shared/mainloop-glib.c:66 #14 0xaaaafa0ad920 in mainloop_run_with_signal src/shared/mainloop-notify.c:188 #15 0xaaaaf9d5489c in main src/main.c:1452 #16 0xffff6dd209d8 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #17 0xffff6dd20aac in __libc_start_main_impl ../csu/libc-start.c:360 #18 0xaaaaf9d5686c in _start (/home/jonas/git/bluez/src/bluetoothd+0x55686c) (BuildId: 8922b026a55aac729ed13de54b3a622a31b5bb2b) previously allocated by thread T0 here: #0 0xffff6ea25218 in calloc (/lib64/libasan.so.8+0xc5218) (BuildId: a77e9fa1e1448d41e9a8ddaf28aa5612f3ffc397) #1 0xffff6e7769e4 in g_malloc0 (/lib64/libglib-2.0.so.0+0x669e4) (BuildId: 7d17ee836a99abf35136ebb46126a95dee66511a) #2 0xaaaaf9db89c4 in media_owner_create profiles/audio/transport.c:514 #3 0xaaaaf9dbd760 in acquire profiles/audio/transport.c:552 #4 0xaaaaf9dbd760 in acquire profiles/audio/transport.c:538 #5 0xaaaaf9ff2574 in process_message gdbus/object.c:246 #6 0xffff6e69de78 in _dbus_object_tree_dispatch_and_unlock ../../dbus/dbus-object-tree.c:1021 #7 0xaaaaf9fe44a4 in message_dispatch gdbus/mainloop.c:59 #8 0xffff6e76c444 in g_idle_dispatch ../glib/gmain.c:6282 #9 0xffff6e77030c in g_main_dispatch ../glib/gmain.c:3476 #10 0xffff6e77030c in g_main_context_dispatch_unlocked ../glib/gmain.c:4284 #11 0xffff6e7ce598 in g_main_context_iterate_unlocked.isra.0 ../glib/gmain.c:4349 #12 0xffff6e771a60 in g_main_loop_run (/lib64/libglib-2.0.so.0+0x61a60) (BuildId: 7d17ee836a99abf35136ebb46126a95dee66511a) #13 0xaaaafa0ad0d8 in mainloop_run src/shared/mainloop-glib.c:66 #14 0xaaaafa0ad920 in mainloop_run_with_signal src/shared/mainloop-notify.c:188 #15 0xaaaaf9d5489c in main src/main.c:1452 #16 0xffff6dd209d8 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #17 0xffff6dd20aac in __libc_start_main_impl ../csu/libc-start.c:360 #18 0xaaaaf9d5686c in _start (/home/jonas/git/bluez/src/bluetoothd+0x55686c) (BuildId: 8922b026a55aac729ed13de54b3a622a31b5bb2b) SUMMARY: AddressSanitizer: heap-use-after-free profiles/audio/transport.c:426 in a2dp_suspend_complete
Hi Silviu, I encountered a use-after-free in the 5.71 release of Bluez which I bisected to this patch. The backtrace is below: #0 0x000055e93dbc8785 in a2dp_suspend_complete (session=<optimized out>, err=0, user_data=0x55e93e432520) at profiles/audio/transport.c:431 #1 0x000055e93dbb97ea in finalize_suspend (data=data@entry=0x55e93e435880) at profiles/audio/a2dp.c:376 #2 0x000055e93dbb98c0 in suspend_cfm (session=0x55e93e4317b0, sep=<optimized out>, stream=<optimized out>, err=0x0, user_data=0x55e93e41e850) at profiles/audio/a2dp.c:1276 #3 0x000055e93dbbfa4b in avdtp_suspend_resp (data=0x55e93e431823, size=<optimized out>, stream=0x55e93e433e60, session=0x55e93e4317b0) at profiles/audio/avdtp.c:2900 #4 avdtp_parse_resp (transaction=<optimized out>, size=<optimized out>, buf=0x55e93e431823, signal_id=<optimized out>, stream=0x55e93e433e60, session=0x55e93e4317b0) at profiles/audio/avdtp.c:2985 #5 session_cb (chan=<optimized out>, cond=<optimized out>, data=0x55e93e4317b0) at profiles/audio/avdtp.c:2286 #6 0x00007f5e225b9f69 in g_main_dispatch (context=0x55e93e3c6800) at ../glib/glib/gmain.c:3476 [...] Originally reported in [1] [1] https://gitlab.archlinux.org/archlinux/packaging/packages/bluez/-/issues/3 Cheers, Ronan
diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c index 1e03b7b51..23ea267f6 100644 --- a/profiles/audio/transport.c +++ b/profiles/audio/transport.c @@ -606,11 +606,38 @@ static DBusMessage *try_acquire(DBusConnection *conn, DBusMessage *msg, return NULL; } +static void bap_stop_complete(struct bt_bap_stream *stream, + uint8_t code, uint8_t reason, + void *user_data) +{ + struct media_owner *owner = user_data; + struct media_request *req = owner->pending; + struct media_transport *transport = owner->transport; + + /* Release always succeeds */ + if (req) { + req->id = 0; + media_request_reply(req, 0); + media_owner_remove(owner); + } + + transport_set_state(transport, TRANSPORT_STATE_IDLE); + media_transport_remove_owner(transport); +} + +static void bap_disable_complete(struct bt_bap_stream *stream, + uint8_t code, uint8_t reason, + void *user_data) +{ + bap_stop_complete(stream, code, reason, user_data); +} + static DBusMessage *release(DBusConnection *conn, DBusMessage *msg, void *data) { struct media_transport *transport = data; struct media_owner *owner = transport->owner; + struct bap_transport *bap = transport->data; const char *sender; struct media_request *req; guint id; @@ -642,6 +669,11 @@ static DBusMessage *release(DBusConnection *conn, DBusMessage *msg, req = media_request_create(msg, id); media_owner_add(owner, req); + if (bt_bap_stream_get_type(bap->stream) == + BT_BAP_STREAM_TYPE_BCAST) { + bap_disable_complete(bap->stream, 0x00, 0x00, owner); + } + return NULL; } @@ -1370,32 +1402,6 @@ static guint resume_bap(struct media_transport *transport, return id; } -static void bap_stop_complete(struct bt_bap_stream *stream, - uint8_t code, uint8_t reason, - void *user_data) -{ - struct media_owner *owner = user_data; - struct media_request *req = owner->pending; - struct media_transport *transport = owner->transport; - - /* Release always succeeds */ - if (req) { - req->id = 0; - media_request_reply(req, 0); - media_owner_remove(owner); - } - - transport_set_state(transport, TRANSPORT_STATE_IDLE); - media_transport_remove_owner(transport); -} - -static void bap_disable_complete(struct bt_bap_stream *stream, - uint8_t code, uint8_t reason, - void *user_data) -{ - bap_stop_complete(stream, code, reason, user_data); -} - static guint suspend_bap(struct media_transport *transport, struct media_owner *owner) { @@ -1499,9 +1505,14 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state, return; break; case BT_BAP_STREAM_STATE_STREAMING: - if (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SOURCE) + if ((bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SOURCE) || + (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SINK)) bap_update_bcast_qos(transport); break; + case BT_BAP_STREAM_STATE_RELEASING: + if (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SINK) + return; + break; } io = bt_bap_stream_get_io(stream);