diff --git a/glib2-fix-race-in-name-watching.patch b/glib2-fix-race-in-name-watching.patch new file mode 100644 index 0000000..875d1f5 --- /dev/null +++ b/glib2-fix-race-in-name-watching.patch @@ -0,0 +1,133 @@ +From b849ebb5d199da3694e6b6261a931436214f7a0e Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Mon, 6 Feb 2017 09:41:10 +0100 +Subject: [PATCH] gdbus: Fix race in name watching on connection teardown +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If g_dbus_unwatch_name() is called from one thread at the same time as +the GDBusConnection is emitting ::disconnected in another thread, there +will be a race and the handler for ::disconnected may end up using +memory after it’s freed. + +Fix this by serialising through the map_id_to_client, so that +on_connection_disconnected() atomically gets a strong reference to the +Client, or NULL. + +https://bugzilla.gnome.org/show_bug.cgi?id=777307 +--- + gio/gdbusnamewatching.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 43 insertions(+), 5 deletions(-) + +diff --git a/gio/gdbusnamewatching.c b/gio/gdbusnamewatching.c +index 3cb2b57b7b0f..148fb41cf025 100644 +--- a/gio/gdbusnamewatching.c ++++ b/gio/gdbusnamewatching.c +@@ -249,13 +249,43 @@ call_vanished_handler (Client *client, + + /* ---------------------------------------------------------------------------------------------------- */ + ++/* Return a reference to the #Client for @watcher_id, or %NULL if it’s been ++ * unwatched. This is safe to call from any thread. */ ++static Client * ++dup_client (guint watcher_id) ++{ ++ Client *client; ++ ++ G_LOCK (lock); ++ ++ g_assert (watcher_id != 0); ++ g_assert (map_id_to_client != NULL); ++ ++ client = g_hash_table_lookup (map_id_to_client, GUINT_TO_POINTER (watcher_id)); ++ ++ if (client != NULL) ++ client_ref (client); ++ ++ G_UNLOCK (lock); ++ ++ return client; ++} ++ ++/* Could be called from any thread, so it could be called after client_unref() ++ * has started finalising the #Client. Avoid that by looking up the #Client ++ * atomically. */ + static void + on_connection_disconnected (GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + gpointer user_data) + { +- Client *client = user_data; ++ guint watcher_id = GPOINTER_TO_UINT (user_data); ++ Client *client = NULL; ++ ++ client = dup_client (watcher_id); ++ if (client == NULL) ++ return; + + if (client->name_owner_changed_subscription_id > 0) + g_dbus_connection_signal_unsubscribe (client->connection, client->name_owner_changed_subscription_id); +@@ -267,10 +297,13 @@ on_connection_disconnected (GDBusConnection *connection, + client->connection = NULL; + + call_vanished_handler (client, FALSE); ++ ++ client_unref (client); + } + + /* ---------------------------------------------------------------------------------------------------- */ + ++/* Will always be called from the thread which acquired client->main_context. */ + static void + on_name_owner_changed (GDBusConnection *connection, + const gchar *sender_name, +@@ -280,11 +313,16 @@ on_name_owner_changed (GDBusConnection *connection, + GVariant *parameters, + gpointer user_data) + { +- Client *client = user_data; ++ guint watcher_id = GPOINTER_TO_UINT (user_data); ++ Client *client = NULL; + const gchar *name; + const gchar *old_owner; + const gchar *new_owner; + ++ client = dup_client (watcher_id); ++ if (client == NULL) ++ return; ++ + if (!client->initialized) + goto out; + +@@ -319,7 +357,7 @@ on_name_owner_changed (GDBusConnection *connection, + } + + out: +- ; ++ client_unref (client); + } + + /* ---------------------------------------------------------------------------------------------------- */ +@@ -444,7 +482,7 @@ has_connection (Client *client) + client->disconnected_signal_handler_id = g_signal_connect (client->connection, + "closed", + G_CALLBACK (on_connection_disconnected), +- client); ++ GUINT_TO_POINTER (client->id)); + + /* start listening to NameOwnerChanged messages immediately */ + client->name_owner_changed_subscription_id = g_dbus_connection_signal_subscribe (client->connection, +@@ -455,7 +493,7 @@ has_connection (Client *client) + client->name, + G_DBUS_SIGNAL_FLAGS_NONE, + on_name_owner_changed, +- client, ++ GUINT_TO_POINTER (client->id), + NULL); + + if (client->flags & G_BUS_NAME_WATCHER_FLAGS_AUTO_START) +-- +2.14.3 + diff --git a/glib2.spec b/glib2.spec index e520962..ae18646 100644 --- a/glib2.spec +++ b/glib2.spec @@ -5,13 +5,16 @@ Name: glib2 Version: 2.52.3 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A library of handy utility functions License: LGPLv2+ URL: http://www.gtk.org Source0: http://download.gnome.org/sources/glib/2.52/glib-%{version}.tar.xz +# https://bugzilla.redhat.com/show_bug.cgi?id=1483205 +Patch0: glib2-fix-race-in-name-watching.patch + BuildRequires: chrpath BuildRequires: gettext BuildRequires: perl-generators @@ -81,6 +84,7 @@ the functionality of the installed glib2 package. %prep %setup -q -n glib-%{version} +%patch0 -p1 -b .race-in-name-watching %build # Bug 1324770: Also explicitly remove PCRE sources since we use --with-pcre=system @@ -229,6 +233,9 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_datadir}/installed-tests %changelog +* Wed Nov 01 2017 Milan Crha - 2.52.3-2 +- Backport fix for race in name watching (RH #1483205) + * Thu Jun 22 2017 Kalev Lember - 2.52.3-1 - Update to 2.52.3