From d44955a199e4202bdac2195774e56141b83aaa14 Mon Sep 17 00:00:00 2001 From: Huang-Huang Bao Date: Thu, 15 Apr 2021 10:01:46 +0800 Subject: [PATCH] a2dp: handle source transport destroy Fix a use-after-free to transport if node is still running. This revert part of a75fe69c8e675d625b04690b32d1b76c6d14744a. --- spa/plugins/bluez5/a2dp-source.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/spa/plugins/bluez5/a2dp-source.c b/spa/plugins/bluez5/a2dp-source.c index 51f49565c..d3e41a503 100644 --- a/spa/plugins/bluez5/a2dp-source.c +++ b/spa/plugins/bluez5/a2dp-source.c @@ -107,6 +107,7 @@ struct impl { struct props props; struct spa_bt_transport *transport; + struct spa_hook transport_listener; struct port port; @@ -1201,6 +1202,31 @@ static const struct spa_node_methods impl_node = { .process = impl_node_process, }; +static int do_transport_destroy(struct spa_loop *loop, + bool async, + uint32_t seq, + const void *data, + size_t size, + void *user_data) +{ + struct impl *this = user_data; + this->transport = NULL; + this->transport_acquired = false; + return 0; +} + +static void transport_destroy(void *data) +{ + struct impl *this = data; + spa_log_debug(this->log, "transport %p destroy", this->transport); + spa_loop_invoke(this->data_loop, do_transport_destroy, 0, NULL, 0, true, this); +} + +static const struct spa_bt_transport_events transport_events = { + SPA_VERSION_BT_TRANSPORT_EVENTS, + .destroy = transport_destroy, +}; + static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface) { struct impl *this; @@ -1225,6 +1251,8 @@ static int impl_clear(struct spa_handle *handle) this->codec->deinit(this->codec_data); if (this->codec_props && this->codec->clear_props) this->codec->clear_props(this->codec_props); + if (this->transport) + spa_hook_remove(&this->transport_listener); return 0; } @@ -1329,6 +1357,9 @@ impl_init(const struct spa_handle_factory *factory, this->codec_props = this->codec->init_props(this->codec, this->transport->device->settings); + spa_bt_transport_add_listener(this->transport, + &this->transport_listener, &transport_events, this); + return 0; }