mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
gdbusinterfaceskeleton: Fix a use-after-free of a GDBusMethodInvocation
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 <pwithnall@endlessos.org> Fixes: #2924
This commit is contained in:
parent
1f86923766
commit
d5710deb9d
@ -462,15 +462,18 @@ typedef struct
|
|||||||
{
|
{
|
||||||
gint ref_count; /* (atomic) */
|
gint ref_count; /* (atomic) */
|
||||||
GDBusInterfaceMethodCallFunc method_call_func;
|
GDBusInterfaceMethodCallFunc method_call_func;
|
||||||
GDBusMethodInvocation *invocation;
|
GDBusMethodInvocation *invocation; /* (owned) */
|
||||||
} DispatchData;
|
} DispatchData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dispatch_data_unref (DispatchData *data)
|
dispatch_data_unref (DispatchData *data)
|
||||||
{
|
{
|
||||||
if (g_atomic_int_dec_and_test (&data->ref_count))
|
if (g_atomic_int_dec_and_test (&data->ref_count))
|
||||||
|
{
|
||||||
|
g_clear_object (&data->invocation);
|
||||||
g_slice_free (DispatchData, data);
|
g_slice_free (DispatchData, data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static DispatchData *
|
static DispatchData *
|
||||||
dispatch_data_ref (DispatchData *data)
|
dispatch_data_ref (DispatchData *data)
|
||||||
@ -628,7 +631,7 @@ g_dbus_interface_method_dispatch_helper (GDBusInterfaceSkeleton *interface
|
|||||||
|
|
||||||
data = g_slice_new0 (DispatchData);
|
data = g_slice_new0 (DispatchData);
|
||||||
data->method_call_func = method_call_func;
|
data->method_call_func = method_call_func;
|
||||||
data->invocation = invocation;
|
data->invocation = g_object_ref (invocation);
|
||||||
data->ref_count = 1;
|
data->ref_count = 1;
|
||||||
|
|
||||||
task = g_task_new (interface, NULL, NULL, NULL);
|
task = g_task_new (interface, NULL, NULL, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user