From c5162672e949ca35cfa494fce0eefe8e24e32bfb Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 10 Jun 2014 13:25:08 +0300 Subject: [PATCH] input: Fix access to uninitialized data when authorizing connections There were bt_io_get() failure code paths in two places that would access "src" and "dst" when they are uninitialized. This would happen e.g. if the HID device disconnects before we've authorized the connection. To fix this we now save the remote address in a more complete confirm context and use the source address already available in the server context. --- profiles/input/server.c | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/profiles/input/server.c b/profiles/input/server.c index 772a605fb..307db96ea 100644 --- a/profiles/input/server.c +++ b/profiles/input/server.c @@ -47,12 +47,17 @@ #include "device.h" #include "server.h" +struct confirm_data { + bdaddr_t dst; + GIOChannel *io; +}; + static GSList *servers = NULL; struct input_server { bdaddr_t src; GIOChannel *ctrl; GIOChannel *intr; - GIOChannel *confirm; + struct confirm_data *confirm; }; static int server_cmp(gconstpointer s, gconstpointer user_data) @@ -191,44 +196,36 @@ static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data) static void auth_callback(DBusError *derr, void *user_data) { struct input_server *server = user_data; - bdaddr_t src, dst; + struct confirm_data *confirm = server->confirm; GError *err = NULL; - bt_io_get(server->confirm, &err, - BT_IO_OPT_SOURCE_BDADDR, &src, - BT_IO_OPT_DEST_BDADDR, &dst, - BT_IO_OPT_INVALID); - if (err) { - error("%s", err->message); - g_error_free(err); - goto reject; - } - if (derr) { error("Access denied: %s", derr->message); goto reject; } - if (!input_device_exists(&src, &dst) && !dev_is_sixaxis(&src, &dst)) + if (!input_device_exists(&server->src, &confirm->dst) && + !dev_is_sixaxis(&server->src, &confirm->dst)) return; - if (!bt_io_accept(server->confirm, connect_event_cb, server, - NULL, &err)) { + if (!bt_io_accept(confirm->io, connect_event_cb, server, NULL, &err)) { error("bt_io_accept: %s", err->message); g_error_free(err); goto reject; } - g_io_channel_unref(server->confirm); + g_io_channel_unref(confirm->io); + g_free(server->confirm); server->confirm = NULL; return; reject: - g_io_channel_shutdown(server->confirm, TRUE, NULL); - g_io_channel_unref(server->confirm); + g_io_channel_shutdown(confirm->io, TRUE, NULL); + g_io_channel_unref(confirm->io); server->confirm = NULL; - input_device_close_channels(&src, &dst); + input_device_close_channels(&server->src, &confirm->dst); + g_free(confirm); } static void confirm_event_cb(GIOChannel *chan, gpointer user_data) @@ -248,7 +245,8 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data) if (err) { error("%s", err->message); g_error_free(err); - goto drop; + g_io_channel_shutdown(chan, TRUE, NULL); + return; } ba2str(&dst, addr); @@ -263,7 +261,9 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data) goto drop; } - server->confirm = g_io_channel_ref(chan); + server->confirm = g_new0(struct confirm_data, 1); + server->confirm->io = g_io_channel_ref(chan); + bacpy(&server->confirm->dst, &dst); ret = btd_request_authorization(&src, &dst, HID_UUID, auth_callback, server); @@ -272,7 +272,8 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data) error("input: authorization for device %s failed", addr); - g_io_channel_unref(server->confirm); + g_io_channel_unref(server->confirm->io); + g_free(server->confirm); server->confirm = NULL; drop: -- 2.47.3