Backport fix for race in name watching (RH #1483205)
This commit is contained in:
parent
3a83a7f74d
commit
fc1fb47dc2
133
glib2-fix-race-in-name-watching.patch
Normal file
133
glib2-fix-race-in-name-watching.patch
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
From b849ebb5d199da3694e6b6261a931436214f7a0e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Philip Withnall <withnall@endlessm.com>
|
||||||
|
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
|
||||||
|
|
@ -5,13 +5,16 @@
|
|||||||
|
|
||||||
Name: glib2
|
Name: glib2
|
||||||
Version: 2.52.3
|
Version: 2.52.3
|
||||||
Release: 1%{?dist}
|
Release: 2%{?dist}
|
||||||
Summary: A library of handy utility functions
|
Summary: A library of handy utility functions
|
||||||
|
|
||||||
License: LGPLv2+
|
License: LGPLv2+
|
||||||
URL: http://www.gtk.org
|
URL: http://www.gtk.org
|
||||||
Source0: http://download.gnome.org/sources/glib/2.52/glib-%{version}.tar.xz
|
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: chrpath
|
||||||
BuildRequires: gettext
|
BuildRequires: gettext
|
||||||
BuildRequires: perl-generators
|
BuildRequires: perl-generators
|
||||||
@ -81,6 +84,7 @@ the functionality of the installed glib2 package.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n glib-%{version}
|
%setup -q -n glib-%{version}
|
||||||
|
%patch0 -p1 -b .race-in-name-watching
|
||||||
|
|
||||||
%build
|
%build
|
||||||
# Bug 1324770: Also explicitly remove PCRE sources since we use --with-pcre=system
|
# 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
|
%{_datadir}/installed-tests
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Nov 01 2017 Milan Crha <mcrha@redhat.com> - 2.52.3-2
|
||||||
|
- Backport fix for race in name watching (RH #1483205)
|
||||||
|
|
||||||
* Thu Jun 22 2017 Kalev Lember <klember@redhat.com> - 2.52.3-1
|
* Thu Jun 22 2017 Kalev Lember <klember@redhat.com> - 2.52.3-1
|
||||||
- Update to 2.52.3
|
- Update to 2.52.3
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user