From 1721258a7d95b8f294d8875ff030eca9b24a2e60 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 1 Apr 2016 17:00:05 +0300 Subject: [PATCH] audio: Fix double free Because avdtp_unref can now cause a state change the stream reference shall be dropped before a2dp_cancel is called otherwise the code may attempt to unref once more using the same reference: Invalid read of size 8 at 0x41F33B: avdtp_set_state (avdtp.c:695) by 0x420CE7: connection_lost (avdtp.c:1118) by 0x4216C4: avdtp_unref (avdtp.c:1178) by 0x418098: source_disconnect (source.c:395) by 0x41D417: a2dp_source_disconnect (a2dp.c:2312) by 0x49A64B: btd_service_disconnect (service.c:273) by 0x49E120: dev_disconn_service (device.c:1325) by 0x50E6DAC: g_slist_foreach (in /usr/lib64/libglib-2.0.so.0.4600.2) by 0x4A3894: device_request_disconnect (device.c:1357) by 0x4A3A3C: dev_disconnect (device.c:1442) by 0x4C7F22: process_message.isra.3 (object.c:259) by 0x4C877C: generic_message (object.c:1071) Address 0x929b0c0 is 16 bytes inside a block of size 1,160 free'd at 0x4C29E00: free (vg_replace_malloc.c:530) by 0x50CE5ED: g_free (in /usr/lib64/libglib-2.0.so.0.4600.2) by 0x42163B: avdtp_free (avdtp.c:1101) by 0x42163B: avdtp_unref (avdtp.c:1182) by 0x417808: source_set_state (source.c:108) by 0x4178F9: avdtp_state_callback (source.c:122) by 0x41F386: avdtp_set_state (avdtp.c:698) by 0x420CE7: connection_lost (avdtp.c:1118) by 0x4216C4: avdtp_unref (avdtp.c:1178) by 0x418098: source_disconnect (source.c:395) by 0x41D417: a2dp_source_disconnect (a2dp.c:2312) by 0x49A64B: btd_service_disconnect (service.c:273) by 0x49E120: dev_disconn_service (device.c:1325) --- profiles/audio/sink.c | 6 +++--- profiles/audio/source.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/profiles/audio/sink.c b/profiles/audio/sink.c index 3167b3aa8..7cac21034 100644 --- a/profiles/audio/sink.c +++ b/profiles/audio/sink.c @@ -396,13 +396,13 @@ int sink_disconnect(struct btd_service *service) /* cancel pending connect */ if (sink->connect_id > 0) { + avdtp_unref(sink->session); + sink->session = NULL; + a2dp_cancel(sink->connect_id); sink->connect_id = 0; btd_service_disconnecting_complete(sink->service, 0); - avdtp_unref(sink->session); - sink->session = NULL; - return 0; } diff --git a/profiles/audio/source.c b/profiles/audio/source.c index 493524e1b..4081e1970 100644 --- a/profiles/audio/source.c +++ b/profiles/audio/source.c @@ -388,13 +388,13 @@ int source_disconnect(struct btd_service *service) /* cancel pending connect */ if (source->connect_id > 0) { + avdtp_unref(source->session); + source->session = NULL; + a2dp_cancel(source->connect_id); source->connect_id = 0; btd_service_disconnecting_complete(source->service, 0); - avdtp_unref(source->session); - source->session = NULL; - return 0; } -- 2.47.3