From: Luiz Augusto von Dentz Date: Mon, 30 Nov 2020 19:16:11 +0000 (-0800) Subject: a2dp: Fix crash if setup is freed while reconfiguring X-Git-Tag: submit/tizen/20220313.220938~543 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8c66e53fd1678df47a5623c6adb18b5d7a4ebcd3;p=platform%2Fupstream%2Fbluez.git a2dp: Fix crash if setup is freed while reconfiguring This fixes the crash reported on: https://github.com/bluez/bluez/issues/60 Signed-off-by: Anuj Jain Signed-off-by: Ayush Garg --- diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c index e05e939..d952f7c 100644 --- a/profiles/audio/a2dp.c +++ b/profiles/audio/a2dp.c @@ -113,6 +113,7 @@ struct a2dp_setup { gboolean start; GSList *cb; GIOChannel *io; + guint id; int ref; }; @@ -215,6 +216,9 @@ static void setup_free(struct a2dp_setup *s) g_io_channel_unref(s->io); } + if (s->id) + g_source_remove(s->id); + queue_destroy(s->eps, NULL); setups = g_slist_remove(setups, s); @@ -1244,6 +1248,8 @@ static gboolean a2dp_reconfigure(gpointer data) struct avdtp_media_codec_capability *rsep_codec; struct avdtp_service_capability *cap; + setup->id = 0; + if (!sep->lsep) { error("no valid local SEP"); posix_err = -EINVAL; @@ -1280,6 +1286,20 @@ failed: return FALSE; } +static bool setup_reconfigure(struct a2dp_setup *setup) +{ + if (!setup->reconfigure || setup->id) + return false; + + DBG("%p", setup); + + setup->id = g_timeout_add(RECONFIGURE_TIMEOUT, a2dp_reconfigure, setup); + + setup->reconfigure = FALSE; + + return true; +} + static struct a2dp_remote_sep *get_remote_sep(struct a2dp_channel *chan, struct avdtp_stream *stream) { @@ -1323,8 +1343,7 @@ static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep, if (!setup->rsep) setup->rsep = get_remote_sep(setup->chan, stream); - if (setup->reconfigure) - g_timeout_add(RECONFIGURE_TIMEOUT, a2dp_reconfigure, setup); + setup_reconfigure(setup); } static void abort_ind(struct avdtp *session, struct avdtp_local_sep *sep, @@ -1368,10 +1387,8 @@ static void abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep, if (!setup) return; - if (setup->reconfigure) { - g_timeout_add(RECONFIGURE_TIMEOUT, a2dp_reconfigure, setup); + if (setup_reconfigure(setup)) return; - } setup_unref(setup); }