From d5710deb9d621bcf0cec0ff2db0708f361490752 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 22 Feb 2023 12:47:36 +0000 Subject: [PATCH] gdbusinterfaceskeleton: Fix a use-after-free of a GDBusMethodInvocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This `GDBusMethodInvocation` may be shared across threads, with no guarantee on the strong ref in one thread outlasting any refs in other threads — so it needs a ref in this helper struct. This should fix a use-after-free where the `GDBusMethodInvocation` is freed from `g_value_unset()` after `g_signal_emit()` returns in `dispatch_in_thread_func()` in one thread; but then dereferenced again in `g_source_destroy_internal()` from another thread. Signed-off-by: Philip Withnall Fixes: #2924 --- gio/gdbusinterfaceskeleton.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c index d28282fea..a2a79fe3d 100644 --- a/gio/gdbusinterfaceskeleton.c +++ b/gio/gdbusinterfaceskeleton.c @@ -462,14 +462,17 @@ typedef struct { gint ref_count; /* (atomic) */ GDBusInterfaceMethodCallFunc method_call_func; - GDBusMethodInvocation *invocation; + GDBusMethodInvocation *invocation; /* (owned) */ } DispatchData; static void dispatch_data_unref (DispatchData *data) { if (g_atomic_int_dec_and_test (&data->ref_count)) - g_slice_free (DispatchData, data); + { + g_clear_object (&data->invocation); + g_slice_free (DispatchData, data); + } } static DispatchData * @@ -628,7 +631,7 @@ g_dbus_interface_method_dispatch_helper (GDBusInterfaceSkeleton *interface data = g_slice_new0 (DispatchData); data->method_call_func = method_call_func; - data->invocation = invocation; + data->invocation = g_object_ref (invocation); data->ref_count = 1; task = g_task_new (interface, NULL, NULL, NULL);