From 9fd2a5879c53e5933402e143ed206e91211d7fd9 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 23 Jan 2017 15:11:02 +0200 Subject: [PATCH] audio/a2dp: Fix possible invalid reads In case the D-Bus endpoint needs to respond or select a configuration for SetConfiguration the setup given as user_data needs to be referenced as the setup can be aborted before there is a reply leading to crash like following the following: Invalid read of size 8 at 0x41B45E: select_cb (a2dp.c:1779) by 0x426881: select_cb (media.c:510) by 0x427A0F: endpoint_reply (media.c:315) by 0x53A7391: ??? (in /usr/lib64/libdbus-1.so.3.16.3) by 0x53AACDE: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.16.3) by 0x4C54EF: message_dispatch (mainloop.c:72) by 0x50C88E6: ??? (in /usr/lib64/libglib-2.0.so.0.5000.2) by 0x50CBE41: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.5000.2) by 0x50CC1BF: ??? (in /usr/lib64/libglib-2.0.so.0.5000.2) by 0x50CC4E1: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.5000.2) by 0x40C85E: main (main.c:708) Address 0x9704de8 is 56 bytes inside a block of size 88 free'd at 0x4C2ED4A: free (vg_replace_malloc.c:530) by 0x50D16BD: g_free (in /usr/lib64/libglib-2.0.so.0.5000.2) by 0x418FAA: setup_free (a2dp.c:166) by 0x418FAA: setup_unref (a2dp.c:178) by 0x41E3DE: a2dp_cancel (a2dp.c:2176) by 0x418244: sink_disconnect (sink.c:402) by 0x41C5B7: a2dp_sink_disconnect (a2dp.c:2344) --- profiles/audio/a2dp.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c index db0736d68..58e1534a4 100644 --- a/profiles/audio/a2dp.c +++ b/profiles/audio/a2dp.c @@ -490,6 +490,7 @@ static void endpoint_setconf_cb(struct a2dp_setup *setup, gboolean ret) } auto_config(setup); + setup_unref(setup); } static gboolean endpoint_match_codec_ind(struct avdtp *session, @@ -579,12 +580,13 @@ static gboolean endpoint_setconf_ind(struct avdtp *session, ret = a2dp_sep->endpoint->set_configuration(a2dp_sep, codec->data, cap->length - sizeof(*codec), - setup, + setup_ref(setup), endpoint_setconf_cb, a2dp_sep->user_data); if (ret == 0) return TRUE; + setup_unref(setup); setup->err = g_new(struct avdtp_error, 1); avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC, AVDTP_UNSUPPORTED_CONFIGURATION); @@ -650,16 +652,18 @@ static void endpoint_open_cb(struct a2dp_setup *setup, gboolean ret) if (ret == FALSE) { setup->stream = NULL; finalize_setup_errno(setup, -EPERM, finalize_config, NULL); - return; + goto done; } err = avdtp_open(setup->session, setup->stream); if (err == 0) - return; + goto done; error("Error on avdtp_open %s (%d)", strerror(-err), -err); setup->stream = NULL; finalize_setup_errno(setup, err, finalize_config, NULL); +done: + setup_unref(setup); } static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, @@ -719,7 +723,7 @@ static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, err = a2dp_sep->endpoint->set_configuration(a2dp_sep, codec->data, service->length - sizeof(*codec), - setup, + setup_ref(setup), endpoint_open_cb, a2dp_sep->user_data); if (err == 0) @@ -727,6 +731,7 @@ static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, setup->stream = NULL; finalize_setup_errno(setup, -EPERM, finalize_config, NULL); + setup_unref(setup); return; } @@ -1791,6 +1796,7 @@ static void select_cb(struct a2dp_setup *setup, void *ret, int size) done: finalize_select(setup); + setup_unref(setup); } static struct a2dp_sep *a2dp_find_sep(struct avdtp *session, GSList *list, @@ -1915,11 +1921,13 @@ unsigned int a2dp_select_capabilities(struct avdtp *session, err = sep->endpoint->select_configuration(sep, codec->data, service->length - sizeof(*codec), - setup, + setup_ref(setup), select_cb, sep->user_data); if (err == 0) return cb_data->id; + setup_unref(setup); + fail: setup_cb_free(cb_data); return 0; -- 2.47.3