The bap_bcast_remove function has been updated to remove from the pa_req queue entries of devices that were freed. pa_req that are already in progress are treated by the bap_data_free function. The lookup in bap_bcast_remove was necessary. The entry corresponding to the calling service must be removed from the pa_req queue. There is no other way to get a refference to this entry other than to search in the queue. This patch fixes a crash that occurs when a device is freed before the pa_idle_timer handles it's entry in the pa_req queue. The following log was obtained while running an Unicast setup: ==105052==ERROR: AddressSanitizer: heap-use-after-free on address 0x60400001c418 at pc 0x55775caf1846 bp 0x7ffc83d9fb90 sp 0x7ffc83d9fb80 READ of size 8 at 0x60400001c418 thread T0 0 0x55775caf1845 in btd_service_get_device src/service.c:325 1 0x55775ca03da2 in short_lived_pa_sync profiles/audio/bap.c:2693 2 0x55775ca03da2 in pa_idle_timer profiles/audio/bap.c:1996 --- profiles/audio/bap.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index ab0b96222..2b1ed501b 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -2981,10 +2981,20 @@ static int bap_bcast_probe(struct btd_service *service) return 0; } +static bool match_service(const void *data, const void *match_data) +{ + struct bap_bcast_pa_req *pa_req = (struct bap_bcast_pa_req *)data; + + if (pa_req->data.service == match_data) + return true; + return false; +} + static void bap_bcast_remove(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct bap_data *data; + struct bap_bcast_pa_req *pa_req; char addr[18]; ba2str(device_get_address(device), addr); @@ -2995,6 +3005,14 @@ static void bap_bcast_remove(struct btd_service *service) error("BAP service not handled by profile"); return; } + /* Remove the corresponding entry from the pa_req queue. Any pa_req that + * are in progress will be stopped by bap_data_remove which calls + * bap_data_free. + */ + pa_req = queue_remove_if(data->bap_adapter->bcast_pa_requests, + match_service, service); + if (pa_req) + free(pa_req); bap_data_remove(data); } -- 2.40.1