From c758622f4625ac3ff87fe3b8f4dcb7e3ab4017e5 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 26 Jan 2017 15:59:01 +0100 Subject: [PATCH] cli: avoid use-after free on connection deletion If the connection spontaneously disappears (perhaps along with the whole daemon on crash) while we're deleting it, then the removal callback would free up the context structure the delete operation is using. Let's cancel the in-flight delete operations so that they won't touch the structure after it's gone. (cherry picked from commit 73b560c215806ab72b1473751ba729a3b5596d69) --- clients/cli/connections.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clients/cli/connections.c b/clients/cli/connections.c index c73f96a980..b9b79ec8f7 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -2704,6 +2704,7 @@ typedef struct { NmCli *nmc; GSList *queue; guint timeout_id; + GCancellable *cancellable; } ConnectionCbInfo; static void connection_cb_info_finish (ConnectionCbInfo *info, @@ -2773,6 +2774,8 @@ connection_cb_info_finish (ConnectionCbInfo *info, gpointer connection) if (info->timeout_id) g_source_remove (info->timeout_id); + g_cancellable_cancel (info->cancellable); + g_object_unref (info->cancellable); g_signal_handlers_disconnect_by_func (info->nmc->client, connection_removed_cb, info); g_slice_free (ConnectionCbInfo, info); quit (); @@ -8280,6 +8283,8 @@ delete_cb (GObject *con, GAsyncResult *result, gpointer user_data) GError *error = NULL; if (!nm_remote_connection_delete_finish (NM_REMOTE_CONNECTION (con), result, &error)) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; g_string_printf (info->nmc->return_text, _("Error: not all connections deleted.")); g_printerr (_("Error: Connection deletion failed: %s"), error->message); @@ -8366,6 +8371,7 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) info->nmc = nmc; info->queue = queue; info->timeout_id = g_timeout_add_seconds (nmc->timeout, connection_op_timeout_cb, info); + info->cancellable = g_cancellable_new (); nmc->nowait_flag = (nmc->timeout == 0); nmc->should_wait++; @@ -8376,7 +8382,7 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) /* Now delete the connections */ for (iter = queue; iter; iter = g_slist_next (iter)) nm_remote_connection_delete_async (NM_REMOTE_CONNECTION (iter->data), - NULL, delete_cb, info); + info->cancellable, delete_cb, info); finish: if (invalid_cons) {