diff --git a/SOURCES/0001-libgdm-drop-support-for-serializing-multiple-opens.patch b/SOURCES/0001-libgdm-drop-support-for-serializing-multiple-opens.patch new file mode 100644 index 0000000..60b0e06 --- /dev/null +++ b/SOURCES/0001-libgdm-drop-support-for-serializing-multiple-opens.patch @@ -0,0 +1,382 @@ +From 30d02d642714b2417be28d430f7d4c602d38a03b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 14 May 2018 14:48:31 -0400 +Subject: [PATCH 01/15] libgdm: drop support for serializing multiple opens + +Right now libgdm tries to handle multiple simultaneous +open calls at the same time by serializing the requests +and giving them all the same connection. It's broken, +though. + + - The pending_opens list is never populated, so we + end up just doing multiple simultaneous open + operations at a time anyway. + - The finish code ends up calling + g_task_return_error (task, NULL) instead of + g_task_return_pointer in the non-error case. + +Since the feature doesn't work, drop it for now. + +https://bugzilla.gnome.org/show_bug.cgi?id=795940 +--- + libgdm/gdm-client.c | 111 ++++++++++++++++---------------------------- + 1 file changed, 40 insertions(+), 71 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index 58ede0aab..06dfe725e 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -24,61 +24,60 @@ + #include + #include + #include + #include + + #include + #include + #include + + #include "gdm-client.h" + #include "gdm-client-glue.h" + #include "gdm-manager-glue.h" + + #define GDM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CLIENT, GdmClientPrivate)) + + #define SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session" + + struct GdmClientPrivate + { + GdmManager *manager; + + GdmUserVerifier *user_verifier; + GHashTable *user_verifier_extensions; + + GdmGreeter *greeter; + GdmRemoteGreeter *remote_greeter; + GdmChooser *chooser; + GDBusConnection *connection; + char *address; + +- GList *pending_opens; + char **enabled_extensions; + }; + + static void gdm_client_class_init (GdmClientClass *klass); + static void gdm_client_init (GdmClient *client); + static void gdm_client_finalize (GObject *object); + + G_DEFINE_TYPE (GdmClient, gdm_client, G_TYPE_OBJECT); + + static gpointer client_object = NULL; + + GQuark + gdm_client_error_quark (void) + { + static GQuark error_quark = 0; + + if (error_quark == 0) + error_quark = g_quark_from_static_string ("gdm-client"); + + return error_quark; + } + + static void + on_got_manager (GdmManager *manager, + GAsyncResult *result, + GTask *task) + { + GdmClient *client; + GdmManager *new_manager; + GError *error; +@@ -396,107 +395,104 @@ on_got_manager_for_reauthentication (GdmClient *client, + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + username = g_object_get_data (G_OBJECT (task), "username"); + gdm_manager_call_open_reauthentication_channel (client->priv->manager, + username, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_opened, + task); + + } + + static gboolean + gdm_client_open_connection_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + +- if (client->priv->manager == NULL) { +- client->priv->manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, +- G_DBUS_PROXY_FLAGS_NONE, +- "org.gnome.DisplayManager", +- "/org/gnome/DisplayManager/Manager", +- cancellable, +- error); +- +- if (client->priv->manager == NULL) { +- goto out; +- } +- } else { +- client->priv->manager = g_object_ref (client->priv->manager); ++ if (client->priv->connection != NULL) { ++ g_object_ref (client->priv->connection); ++ return TRUE; + } + +- if (client->priv->connection == NULL) { +- ret = gdm_manager_call_open_session_sync (client->priv->manager, +- &client->priv->address, +- cancellable, +- error); ++ client->priv->manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_NONE, ++ "org.gnome.DisplayManager", ++ "/org/gnome/DisplayManager/Manager", ++ cancellable, ++ error); + +- if (!ret) { +- g_clear_object (&client->priv->manager); +- goto out; +- } ++ if (client->priv->manager == NULL) { ++ goto out; ++ } ++ ++ ret = gdm_manager_call_open_session_sync (client->priv->manager, ++ &client->priv->address, ++ cancellable, ++ error); + +- g_debug ("GdmClient: connecting to address: %s", client->priv->address); ++ if (!ret) { ++ g_clear_object (&client->priv->manager); ++ goto out; ++ } + +- client->priv->connection = g_dbus_connection_new_for_address_sync (client->priv->address, +- G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, +- NULL, +- cancellable, +- error); ++ g_debug ("GdmClient: connecting to address: %s", client->priv->address); + +- if (client->priv->connection == NULL) { +- g_clear_object (&client->priv->manager); +- g_clear_pointer (&client->priv->address, g_free); +- goto out; +- } ++ client->priv->connection = g_dbus_connection_new_for_address_sync (client->priv->address, ++ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, ++ NULL, ++ cancellable, ++ error); + +- g_object_add_weak_pointer (G_OBJECT (client->priv->connection), +- (gpointer *) +- &client->priv->connection); +- } else { +- client->priv->connection = g_object_ref (client->priv->connection); ++ if (client->priv->connection == NULL) { ++ g_clear_object (&client->priv->manager); ++ g_clear_pointer (&client->priv->address, g_free); ++ goto out; + } + ++ g_object_add_weak_pointer (G_OBJECT (client->priv->connection), ++ (gpointer *) ++ &client->priv->connection); ++ + out: + return client->priv->connection != NULL; + } + + static void + on_connected (GObject *source_object, + GAsyncResult *result, + GTask *task) + { + GDBusConnection *connection; + GError *error; + + error = NULL; + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (!connection) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + g_object_ref (connection), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + g_object_unref (connection); + } + + static void + on_session_opened (GdmManager *manager, + GAsyncResult *result, +@@ -528,140 +524,113 @@ on_session_opened (GdmManager *manager, + on_connected, + task); + g_object_unref (client); + } + + static void + on_got_manager_for_opening_connection (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_manager_call_open_session (client->priv->manager, + cancellable, + (GAsyncReadyCallback) + on_session_opened, + task); + } + +-static void +-finish_pending_opens (GdmClient *client, +- GError *error) +-{ +- GList *node; +- +- for (node = client->priv->pending_opens; +- node != NULL; +- node = node->next) { +- +- GTask *task = node->data; +- +- g_task_return_error (task, error); +- g_object_unref (task); +- } +- g_clear_pointer (&client->priv->pending_opens, +- (GDestroyNotify) g_list_free); +-} +- + static gboolean + gdm_client_open_connection_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { +- finish_pending_opens (client, *error); + return FALSE; + } + + if (client->priv->connection == NULL) { + client->priv->connection = g_steal_pointer (&connection); + g_object_add_weak_pointer (G_OBJECT (client->priv->connection), + (gpointer *) &client->priv->connection); + } else if (client->priv->connection == connection) { + connection = NULL; + } + +- finish_pending_opens (client, NULL); + return TRUE; + } + + static void + gdm_client_open_connection (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->connection != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->connection), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + +- if (client->priv->pending_opens == NULL) { +- get_manager (client, +- cancellable, +- (GAsyncReadyCallback) +- on_got_manager_for_opening_connection, +- task); +- } else { +- client->priv->pending_opens = g_list_prepend (client->priv->pending_opens, +- task); +- } +- ++ get_manager (client, ++ cancellable, ++ (GAsyncReadyCallback) ++ on_got_manager_for_opening_connection, ++ task); + } + + /** + * gdm_client_open_reauthentication_channel_sync: + * @client: a #GdmClient + * @username: user to reauthenticate + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. Free with + * g_object_unref to close reauthentication channel. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not + * already logged in. + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_sync (GdmClient *client, + const char *username, + GCancellable *cancellable, + GError **error) + { + GDBusConnection *connection; + GdmUserVerifier *user_verifier = NULL; + gboolean ret; + char *address; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->manager == NULL) { +-- +2.26.2 + diff --git a/SOURCES/0002-libgdm-don-t-keep-manager-proxy-around-longer-than-w.patch b/SOURCES/0002-libgdm-don-t-keep-manager-proxy-around-longer-than-w.patch new file mode 100644 index 0000000..a5ae0d0 --- /dev/null +++ b/SOURCES/0002-libgdm-don-t-keep-manager-proxy-around-longer-than-w.patch @@ -0,0 +1,1029 @@ +From 1a590b855f5b5d323334b49707778d4ee88ba873 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 14 May 2018 15:57:14 -0400 +Subject: [PATCH 02/15] libgdm: don't keep manager proxy around longer than we + need it +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Right now we keep the manager proxy alive long after we need it. +It doesn't get cleared until one of the other proxies go away. + +That is not only unnecessary but illogical and confusing. + +This commit changes the manager proxy to be transient—only alive +long enough to get what we need from it. + +https://bugzilla.gnome.org/show_bug.cgi?id=795940 +--- + libgdm/gdm-client.c | 119 ++++++++++---------------------------------- + 1 file changed, 26 insertions(+), 93 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index 06dfe725e..e02e3ea57 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -13,150 +13,130 @@ + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + #include "config.h" + + #include + #include + #include + #include + + #include + #include + #include + + #include "gdm-client.h" + #include "gdm-client-glue.h" + #include "gdm-manager-glue.h" + + #define GDM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CLIENT, GdmClientPrivate)) + + #define SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session" + + struct GdmClientPrivate + { +- GdmManager *manager; +- + GdmUserVerifier *user_verifier; + GHashTable *user_verifier_extensions; + + GdmGreeter *greeter; + GdmRemoteGreeter *remote_greeter; + GdmChooser *chooser; + GDBusConnection *connection; + char *address; + + char **enabled_extensions; + }; + + static void gdm_client_class_init (GdmClientClass *klass); + static void gdm_client_init (GdmClient *client); + static void gdm_client_finalize (GObject *object); + + G_DEFINE_TYPE (GdmClient, gdm_client, G_TYPE_OBJECT); + + static gpointer client_object = NULL; + + GQuark + gdm_client_error_quark (void) + { + static GQuark error_quark = 0; + + if (error_quark == 0) + error_quark = g_quark_from_static_string ("gdm-client"); + + return error_quark; + } + + static void +-on_got_manager (GdmManager *manager, ++on_got_manager (GObject *object, + GAsyncResult *result, + GTask *task) + { + GdmClient *client; +- GdmManager *new_manager; +- GError *error; ++ GError *error; ++ g_autoptr(GdmManager) manager = NULL; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); + + error = NULL; +- new_manager = gdm_manager_proxy_new_finish (result, &error); +- +- if (client->priv->manager == NULL) { +- client->priv->manager = new_manager; +- +- } else { +- g_object_ref (client->priv->manager); +- g_object_unref (new_manager); +- +- g_clear_error (&error); +- } ++ manager = gdm_manager_proxy_new_finish (result, &error); + + if (error != NULL) { + g_task_return_error (task, error); + } else { + g_task_return_pointer (task, +- g_object_ref (client->priv->manager), ++ g_object_ref (manager), + (GDestroyNotify) g_object_unref); + } + + g_object_unref (task); + g_object_unref (client); + } + + static void + get_manager (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + +- if (client->priv->manager != NULL) { +- g_task_return_pointer (task, +- g_object_ref (client->priv->manager), +- (GDestroyNotify) g_object_unref); +- g_object_unref (task); +- return; +- } +- + gdm_manager_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + (GAsyncReadyCallback) + on_got_manager, + task); + } + + typedef struct { + GTask *task; + GdmUserVerifier *user_verifier; + } UserVerifierData; + + static UserVerifierData * + user_verifier_data_new (GTask *task, GdmUserVerifier *user_verifier) + { + UserVerifierData *data; + + data = g_slice_new (UserVerifierData); + data->task = g_object_ref (task); + data->user_verifier = g_object_ref (user_verifier); + + return data; + } + + static void + user_verifier_data_free (UserVerifierData *data) + { +@@ -377,114 +357,113 @@ on_reauthentication_channel_opened (GdmManager *manager, + cancellable = g_task_get_cancellable (task); + g_dbus_connection_new_for_address (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_connected, + task); + } + + static void + on_got_manager_for_reauthentication (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + char *username; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + username = g_object_get_data (G_OBJECT (task), "username"); +- gdm_manager_call_open_reauthentication_channel (client->priv->manager, ++ gdm_manager_call_open_reauthentication_channel (manager, + username, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_opened, + task); + + } + + static gboolean + gdm_client_open_connection_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { ++ g_autoptr(GdmManager) manager = NULL; + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->connection != NULL) { + g_object_ref (client->priv->connection); + return TRUE; + } + +- client->priv->manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, +- G_DBUS_PROXY_FLAGS_NONE, +- "org.gnome.DisplayManager", +- "/org/gnome/DisplayManager/Manager", +- cancellable, +- error); ++ manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_NONE, ++ "org.gnome.DisplayManager", ++ "/org/gnome/DisplayManager/Manager", ++ cancellable, ++ error); + +- if (client->priv->manager == NULL) { ++ if (manager == NULL) { + goto out; + } + +- ret = gdm_manager_call_open_session_sync (client->priv->manager, ++ ret = gdm_manager_call_open_session_sync (manager, + &client->priv->address, + cancellable, + error); + + if (!ret) { +- g_clear_object (&client->priv->manager); + goto out; + } + + g_debug ("GdmClient: connecting to address: %s", client->priv->address); + + client->priv->connection = g_dbus_connection_new_for_address_sync (client->priv->address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + + if (client->priv->connection == NULL) { +- g_clear_object (&client->priv->manager); + g_clear_pointer (&client->priv->address, g_free); + goto out; + } + + g_object_add_weak_pointer (G_OBJECT (client->priv->connection), + (gpointer *) + &client->priv->connection); + + out: + return client->priv->connection != NULL; + } + + static void + on_connected (GObject *source_object, + GAsyncResult *result, + GTask *task) + { + GDBusConnection *connection; + GError *error; + + error = NULL; + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (!connection) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + g_object_ref (connection), +@@ -517,61 +496,61 @@ on_session_opened (GdmManager *manager, + + cancellable = g_task_get_cancellable (task); + g_dbus_connection_new_for_address (client->priv->address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + (GAsyncReadyCallback) + on_connected, + task); + g_object_unref (client); + } + + static void + on_got_manager_for_opening_connection (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); +- gdm_manager_call_open_session (client->priv->manager, ++ gdm_manager_call_open_session (manager, + cancellable, + (GAsyncReadyCallback) + on_session_opened, + task); + } + + static gboolean + gdm_client_open_connection_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { + return FALSE; + } + + if (client->priv->connection == NULL) { + client->priv->connection = g_steal_pointer (&connection); + g_object_add_weak_pointer (G_OBJECT (client->priv->connection), + (gpointer *) &client->priv->connection); + } else if (client->priv->connection == connection) { + connection = NULL; + } + + return TRUE; + } +@@ -600,122 +579,114 @@ gdm_client_open_connection (GdmClient *client, + } + + get_manager (client, + cancellable, + (GAsyncReadyCallback) + on_got_manager_for_opening_connection, + task); + } + + /** + * gdm_client_open_reauthentication_channel_sync: + * @client: a #GdmClient + * @username: user to reauthenticate + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. Free with + * g_object_unref to close reauthentication channel. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not + * already logged in. + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_sync (GdmClient *client, + const char *username, + GCancellable *cancellable, + GError **error) + { + GDBusConnection *connection; ++ g_autoptr(GdmManager) manager = NULL; + GdmUserVerifier *user_verifier = NULL; + gboolean ret; + char *address; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + +- if (client->priv->manager == NULL) { +- client->priv->manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, +- G_DBUS_PROXY_FLAGS_NONE, +- "org.gnome.DisplayManager", +- "/org/gnome/DisplayManager/Manager", +- cancellable, +- error); ++ manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_NONE, ++ "org.gnome.DisplayManager", ++ "/org/gnome/DisplayManager/Manager", ++ cancellable, ++ error); + +- if (client->priv->manager == NULL) { +- goto out; +- } +- } else { +- client->priv->manager = g_object_ref (client->priv->manager); ++ if (manager == NULL) { ++ goto out; + } + +- ret = gdm_manager_call_open_reauthentication_channel_sync (client->priv->manager, ++ ret = gdm_manager_call_open_reauthentication_channel_sync (manager, + username, + &address, + cancellable, + error); + + if (!ret) { + goto out; + } + + g_debug ("GdmClient: connecting to address: %s", client->priv->address); + + connection = g_dbus_connection_new_for_address_sync (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + + if (connection == NULL) { + g_free (address); + goto out; + } + g_free (address); + + user_verifier = gdm_user_verifier_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (user_verifier != NULL) { + g_object_weak_ref (G_OBJECT (user_verifier), + (GWeakNotify) + g_object_unref, + connection); +- +- g_object_weak_ref (G_OBJECT (user_verifier), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); + } + + out: + return user_verifier; + } + + /** + * gdm_client_open_reauthentication_channel: + * @client: a #GdmClient + * @username: user to reauthenticate + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. + */ + void + gdm_client_open_reauthentication_channel (GdmClient *client, + const char *username, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, +@@ -764,64 +735,60 @@ gdm_client_open_reauthentication_channel_finish (GdmClient *client, + * + * Gets a #GdmUserVerifier object that can be used to + * verify a user's local account. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if not connected + */ + GdmUserVerifier * + gdm_client_get_user_verifier_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + if (client->priv->user_verifier != NULL) { + return g_object_ref (client->priv->user_verifier); + } + + if (!gdm_client_open_connection_sync (client, cancellable, error)) { + return NULL; + } + + client->priv->user_verifier = gdm_user_verifier_proxy_new_sync (client->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->user_verifier != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); +- g_object_weak_ref (G_OBJECT (client->priv->user_verifier), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); + g_object_weak_ref (G_OBJECT (client->priv->user_verifier), + (GWeakNotify) + g_object_unref, + client->priv->connection); + + if (client->priv->enabled_extensions != NULL) { + gboolean res; + + client->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) + free_interface_skeleton); + res = gdm_user_verifier_call_enable_extensions_sync (client->priv->user_verifier, + (const char * const *) + client->priv->enabled_extensions, + cancellable, + NULL); + + if (res) { + size_t i; + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + GdmUserVerifierChoiceList *choice_list_interface; + choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (client->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, +@@ -914,65 +881,60 @@ gdm_client_get_user_verifier (GdmClient *client, + * + * Returns: (transfer full): a #GdmUserVerifier + */ + GdmUserVerifier * + gdm_client_get_user_verifier_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmUserVerifier *user_verifier; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->user_verifier != NULL) + return g_object_ref (client->priv->user_verifier); + + user_verifier = g_task_propagate_pointer (G_TASK (result), error); + if (user_verifier == NULL) + return NULL; + + client->priv->user_verifier = user_verifier; + + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + + g_object_weak_ref (G_OBJECT (client->priv->user_verifier), + (GWeakNotify) + g_object_unref, + client->priv->connection); + +- g_object_weak_ref (G_OBJECT (client->priv->user_verifier), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); +- + return user_verifier; + } + + /** + * gdm_client_get_user_verifier_choice_list: + * @client: a #GdmClient + * + * Gets a #GdmUserVerifierChoiceList object that can be used to + * verify a user's local account. + * + * Returns: (transfer none): #GdmUserVerifierChoiceList or %NULL if user + * verifier isn't yet fetched, or daemon doesn't support choice lists + */ + GdmUserVerifierChoiceList * + gdm_client_get_user_verifier_choice_list (GdmClient *client) + { + if (client->priv->user_verifier_extensions == NULL) + return NULL; + + return g_hash_table_lookup (client->priv->user_verifier_extensions, + gdm_user_verifier_choice_list_interface_info ()->name); + } + + static void + on_timed_login_details_got (GdmGreeter *greeter, + GAsyncResult *result) + { + gdm_greeter_call_get_timed_login_details_finish (greeter, NULL, NULL, NULL, result, NULL); + } + +@@ -1088,110 +1050,100 @@ gdm_client_get_greeter (GdmClient *client, + * gdm_client_get_greeter(). + * + * Returns: (transfer full): a #GdmGreeter + */ + GdmGreeter * + gdm_client_get_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmGreeter *greeter; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->greeter != NULL) + return g_object_ref (client->priv->greeter); + + greeter = g_task_propagate_pointer (G_TASK (result), error); + if (greeter == NULL) + return NULL; + + client->priv->greeter = greeter; + + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + + g_object_weak_ref (G_OBJECT (client->priv->greeter), + (GWeakNotify) + g_object_unref, + client->priv->connection); +- +- g_object_weak_ref (G_OBJECT (client->priv->greeter), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); +- + return greeter; + } + + /** + * gdm_client_get_greeter_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmGreeter object that can be used + * to do do various login screen related tasks, such + * as selecting a users session, and starting that + * session. + * + * Returns: (transfer full): #GdmGreeter or %NULL if caller is not a greeter + */ + GdmGreeter * + gdm_client_get_greeter_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + if (client->priv->greeter != NULL) { + return g_object_ref (client->priv->greeter); + } + + if (!gdm_client_open_connection_sync (client, cancellable, error)) { + return NULL; + } + + client->priv->greeter = gdm_greeter_proxy_new_sync (client->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); +- g_object_weak_ref (G_OBJECT (client->priv->greeter), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); + g_object_weak_ref (G_OBJECT (client->priv->greeter), + (GWeakNotify) + g_object_unref, + client->priv->connection); + + query_for_timed_login_requested_signal (client->priv->greeter); + } + + return client->priv->greeter; + } + + static void + on_remote_greeter_proxy_created (GObject *object, + GAsyncResult *result, + GTask *task) + { + GdmRemoteGreeter *remote_greeter; + GError *error = NULL; + + remote_greeter = gdm_remote_greeter_proxy_new_finish (result, &error); + if (remote_greeter == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + remote_greeter, + (GDestroyNotify) g_object_unref); + g_object_unref (task); +@@ -1274,108 +1226,99 @@ gdm_client_get_remote_greeter (GdmClient *client, + * + * Returns: (transfer full): a #GdmRemoteGreeter + */ + GdmRemoteGreeter * + gdm_client_get_remote_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmRemoteGreeter *remote_greeter; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->remote_greeter != NULL) + return g_object_ref (client->priv->remote_greeter); + + remote_greeter = g_task_propagate_pointer (G_TASK (result), error); + if (remote_greeter == NULL) + return NULL; + + client->priv->remote_greeter = remote_greeter; + + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + + g_object_weak_ref (G_OBJECT (client->priv->remote_greeter), + (GWeakNotify) + g_object_unref, + client->priv->connection); + +- g_object_weak_ref (G_OBJECT (client->priv->remote_greeter), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); +- + return remote_greeter; + } + + /** + * gdm_client_get_remote_greeter_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmRemoteGreeter object that can be used + * to do do various remote login screen related tasks, + * such as disconnecting. + * + * Returns: (transfer full): #GdmRemoteGreeter or %NULL if caller is not remote + */ + GdmRemoteGreeter * + gdm_client_get_remote_greeter_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + if (client->priv->remote_greeter != NULL) { + return g_object_ref (client->priv->remote_greeter); + } + + if (!gdm_client_open_connection_sync (client, cancellable, error)) { + return NULL; + } + + client->priv->remote_greeter = gdm_remote_greeter_proxy_new_sync (client->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->remote_greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); +- g_object_weak_ref (G_OBJECT (client->priv->remote_greeter), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); + g_object_weak_ref (G_OBJECT (client->priv->remote_greeter), + (GWeakNotify) + g_object_unref, + client->priv->connection); + } + + return client->priv->remote_greeter; + } + + static void + on_chooser_proxy_created (GObject *source, + GAsyncResult *result, + GTask *task) + { + GdmChooser *chooser; + GError *error = NULL; + + chooser = gdm_chooser_proxy_new_finish (result, &error); + if (chooser == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + chooser, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + } + +@@ -1456,109 +1399,100 @@ gdm_client_get_chooser (GdmClient *client, + * + * Returns: (transfer full): a #GdmChooser + */ + GdmChooser * + gdm_client_get_chooser_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmChooser *chooser; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->chooser != NULL) + return g_object_ref (client->priv->chooser); + + chooser = g_task_propagate_pointer (G_TASK (result), error); + if (chooser == NULL) + return NULL; + + client->priv->chooser = chooser; + + g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + + g_object_weak_ref (G_OBJECT (client->priv->chooser), + (GWeakNotify) + g_object_unref, + client->priv->connection); + +- g_object_weak_ref (G_OBJECT (client->priv->chooser), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); +- + return chooser; + } + + /** + * gdm_client_get_chooser_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmChooser object that can be used + * to do do various XDMCP chooser related tasks, such + * as selecting a host or disconnecting. + * + * Returns: (transfer full): #GdmChooser or %NULL if caller is not a chooser + */ + GdmChooser * + gdm_client_get_chooser_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + + if (client->priv->chooser != NULL) { + return g_object_ref (client->priv->chooser); + } + + if (!gdm_client_open_connection_sync (client, cancellable, error)) { + return NULL; + } + + client->priv->chooser = gdm_chooser_proxy_new_sync (client->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->chooser != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); +- g_object_weak_ref (G_OBJECT (client->priv->chooser), +- (GWeakNotify) +- g_clear_object, +- &client->priv->manager); + g_object_weak_ref (G_OBJECT (client->priv->chooser), + (GWeakNotify) + g_object_unref, + client->priv->connection); + } + + return client->priv->chooser; + } + + static void + gdm_client_class_init (GdmClientClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gdm_client_finalize; + + g_type_class_add_private (klass, sizeof (GdmClientPrivate)); + + } + + static void + gdm_client_init (GdmClient *client) + { + + client->priv = GDM_CLIENT_GET_PRIVATE (client); + } + + static void + gdm_client_finalize (GObject *object) + { +@@ -1574,61 +1508,60 @@ gdm_client_finalize (GObject *object) + if (client->priv->user_verifier != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + } + + if (client->priv->greeter != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + } + + if (client->priv->remote_greeter != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + } + + if (client->priv->chooser != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + } + + if (client->priv->connection != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->connection), + (gpointer *) + &client->priv->connection); + } + +- g_clear_object (&client->priv->manager); + g_clear_object (&client->priv->connection); + + g_strfreev (client->priv->enabled_extensions); + g_free (client->priv->address); + + G_OBJECT_CLASS (gdm_client_parent_class)->finalize (object); + } + + GdmClient * + gdm_client_new (void) + { + if (client_object != NULL) { + g_object_ref (client_object); + } else { + client_object = g_object_new (GDM_TYPE_CLIENT, NULL); + g_object_add_weak_pointer (client_object, + (gpointer *) &client_object); + } + + return GDM_CLIENT (client_object); + } + + + /** + * gdm_client_set_enabled_extensions: + * @client: a #GdmClient + * @extensions: (array zero-terminated=1) (element-type utf8): a list of extensions + * + * Enables GDM's pam extensions. Currently, only + * org.gnome.DisplayManager.UserVerifier.ChoiceList is supported. +-- +2.26.2 + diff --git a/SOURCES/0003-libgdm-get-connection-explicitly.patch b/SOURCES/0003-libgdm-get-connection-explicitly.patch new file mode 100644 index 0000000..0dd2f44 --- /dev/null +++ b/SOURCES/0003-libgdm-get-connection-explicitly.patch @@ -0,0 +1,1046 @@ +From ee771715164b157d5dbe368a7771d0018a47a27c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Mon, 14 May 2018 16:32:25 -0400 +Subject: [PATCH 03/15] libgdm: get connection explicitly + +At the moment we call gdm_client_open_connection and when it finishes, +assume client->priv->connection is implicitly initialized. + +This commit makes the operation more explicit by changing +gdm_client_open_connection to gdm_client_get_connection and returning +the GDBusConnection object directly, instead of returning a boolean. + +https://bugzilla.gnome.org/show_bug.cgi?id=795940 +--- + libgdm/gdm-client.c | 136 ++++++++++++++++++++++++++------------------ + 1 file changed, 82 insertions(+), 54 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index e02e3ea57..e7b93e382 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -366,114 +366,113 @@ on_reauthentication_channel_opened (GdmManager *manager, + + static void + on_got_manager_for_reauthentication (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + char *username; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + username = g_object_get_data (G_OBJECT (task), "username"); + gdm_manager_call_open_reauthentication_channel (manager, + username, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_opened, + task); + + } + +-static gboolean +-gdm_client_open_connection_sync (GdmClient *client, +- GCancellable *cancellable, +- GError **error) ++static GDBusConnection * ++gdm_client_get_connection_sync (GdmClient *client, ++ GCancellable *cancellable, ++ GError **error) + { + g_autoptr(GdmManager) manager = NULL; + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->connection != NULL) { +- g_object_ref (client->priv->connection); +- return TRUE; ++ return g_object_ref (client->priv->connection); + } + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + goto out; + } + + ret = gdm_manager_call_open_session_sync (manager, + &client->priv->address, + cancellable, + error); + + if (!ret) { + goto out; + } + + g_debug ("GdmClient: connecting to address: %s", client->priv->address); + + client->priv->connection = g_dbus_connection_new_for_address_sync (client->priv->address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + + if (client->priv->connection == NULL) { + g_clear_pointer (&client->priv->address, g_free); + goto out; + } + + g_object_add_weak_pointer (G_OBJECT (client->priv->connection), + (gpointer *) + &client->priv->connection); + + out: +- return client->priv->connection != NULL; ++ return client->priv->connection; + } + + static void + on_connected (GObject *source_object, + GAsyncResult *result, + GTask *task) + { + GDBusConnection *connection; + GError *error; + + error = NULL; + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (!connection) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + g_object_ref (connection), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + g_object_unref (connection); + } + + static void + on_session_opened (GdmManager *manager, + GAsyncResult *result, + GTask *task) + { +@@ -503,87 +502,85 @@ on_session_opened (GdmManager *manager, + on_connected, + task); + g_object_unref (client); + } + + static void + on_got_manager_for_opening_connection (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_manager_call_open_session (manager, + cancellable, + (GAsyncReadyCallback) + on_session_opened, + task); + } + +-static gboolean +-gdm_client_open_connection_finish (GdmClient *client, +- GAsyncResult *result, +- GError **error) ++static GDBusConnection * ++gdm_client_get_connection_finish (GdmClient *client, ++ GAsyncResult *result, ++ GError **error) + { +- g_autoptr(GDBusConnection) connection = NULL; ++ GDBusConnection *connection = NULL; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { +- return FALSE; ++ return NULL; + } + + if (client->priv->connection == NULL) { +- client->priv->connection = g_steal_pointer (&connection); ++ client->priv->connection = connection; + g_object_add_weak_pointer (G_OBJECT (client->priv->connection), + (gpointer *) &client->priv->connection); +- } else if (client->priv->connection == connection) { +- connection = NULL; + } + +- return TRUE; ++ return g_object_ref (connection); + } + + static void +-gdm_client_open_connection (GdmClient *client, ++gdm_client_get_connection (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->connection != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->connection), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + + get_manager (client, + cancellable, + (GAsyncReadyCallback) + on_got_manager_for_opening_connection, + task); + } + + /** + * gdm_client_open_reauthentication_channel_sync: +@@ -716,184 +713,192 @@ gdm_client_open_reauthentication_channel (GdmClient *client, + * gdm_client_open_reauthentication_channel(). + * + * Returns: (transfer full): a #GdmUserVerifier + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + return g_task_propagate_pointer (G_TASK (result), error); + } + + /** + * gdm_client_get_user_verifier_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * verify a user's local account. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if not connected + */ + GdmUserVerifier * + gdm_client_get_user_verifier_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { ++ g_autoptr(GDBusConnection) connection = NULL; ++ + if (client->priv->user_verifier != NULL) { + return g_object_ref (client->priv->user_verifier); + } + +- if (!gdm_client_open_connection_sync (client, cancellable, error)) { ++ connection = gdm_client_get_connection_sync (client, cancellable, error); ++ ++ if (connection == NULL) { + return NULL; + } + +- client->priv->user_verifier = gdm_user_verifier_proxy_new_sync (client->priv->connection, ++ client->priv->user_verifier = gdm_user_verifier_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->user_verifier != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); ++ g_object_ref (connection); + g_object_weak_ref (G_OBJECT (client->priv->user_verifier), + (GWeakNotify) + g_object_unref, + client->priv->connection); + + if (client->priv->enabled_extensions != NULL) { + gboolean res; + + client->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) + free_interface_skeleton); + res = gdm_user_verifier_call_enable_extensions_sync (client->priv->user_verifier, + (const char * const *) + client->priv->enabled_extensions, + cancellable, + NULL); + + if (res) { + size_t i; + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + GdmUserVerifierChoiceList *choice_list_interface; + choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (client->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + NULL); + if (choice_list_interface != NULL) + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], choice_list_interface); + } + } + } + } + } + + return client->priv->user_verifier; + } + + static void +-on_connection_opened_for_user_verifier (GdmClient *client, +- GAsyncResult *result, +- GTask *task) ++on_connection_for_user_verifier (GdmClient *client, ++ GAsyncResult *result, ++ GTask *task) + { ++ g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; + GError *error; + + error = NULL; +- if (!gdm_client_open_connection_finish (client, result, &error)) { ++ connection = gdm_client_get_connection_finish (client, result, &error); ++ ++ if (connection == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); +- gdm_user_verifier_proxy_new (client->priv->connection, ++ gdm_user_verifier_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + (GAsyncReadyCallback) + on_user_verifier_proxy_created, + task); + } + + /** + * gdm_client_get_user_verifier: + * @client: a #GdmClient + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmUserVerifier object that can be used to + * verify a user's local account. + */ + void + gdm_client_get_user_verifier (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->user_verifier != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->user_verifier), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + +- gdm_client_open_connection (client, ++ gdm_client_get_connection (client, + cancellable, + (GAsyncReadyCallback) +- on_connection_opened_for_user_verifier, ++ on_connection_for_user_verifier, + task); + } + + /** + * gdm_client_get_user_verifier_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_user_verifier(). + * + * Returns: (transfer full): a #GdmUserVerifier + */ + GdmUserVerifier * + gdm_client_get_user_verifier_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmUserVerifier *user_verifier; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->user_verifier != NULL) + return g_object_ref (client->priv->user_verifier); + + user_verifier = g_task_propagate_pointer (G_TASK (result), error); + if (user_verifier == NULL) + return NULL; + +@@ -948,122 +953,125 @@ query_for_timed_login_requested_signal (GdmGreeter *greeter) + NULL, + (GAsyncReadyCallback) + on_timed_login_details_got, + NULL); + } + + static void + on_greeter_proxy_created (GObject *source, + GAsyncResult *result, + GTask *task) + { + GdmGreeter *greeter; + GError *error = NULL; + + greeter = gdm_greeter_proxy_new_finish (result, &error); + if (greeter == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + greeter, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + + query_for_timed_login_requested_signal (greeter); + } + + static void +-on_connection_opened_for_greeter (GdmClient *client, +- GAsyncResult *result, +- GTask *task) ++on_connection_for_greeter (GdmClient *client, ++ GAsyncResult *result, ++ GTask *task) + { ++ g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; + GError *error; + + error = NULL; +- if (!gdm_client_open_connection_finish (client, result, &error)) { ++ connection = gdm_client_get_connection_finish (client, result, &error); ++ ++ if (connection == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); +- gdm_greeter_proxy_new (client->priv->connection, ++ gdm_greeter_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + (GAsyncReadyCallback) + on_greeter_proxy_created, + task); + } + + /** + * gdm_client_get_greeter: + * @client: a #GdmClient + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmGreeter object that can be used to + * verify a user's local account. + */ + void + gdm_client_get_greeter (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->greeter != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->greeter), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + +- gdm_client_open_connection (client, ++ gdm_client_get_connection (client, + cancellable, + (GAsyncReadyCallback) +- on_connection_opened_for_greeter, ++ on_connection_for_greeter, + task); + } + + /** + * gdm_client_get_greeter_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_greeter(). + * + * Returns: (transfer full): a #GdmGreeter + */ + GdmGreeter * + gdm_client_get_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmGreeter *greeter; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->greeter != NULL) + return g_object_ref (client->priv->greeter); + + greeter = g_task_propagate_pointer (G_TASK (result), error); + if (greeter == NULL) + return NULL; + +@@ -1071,174 +1079,181 @@ gdm_client_get_greeter_finish (GdmClient *client, + + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + + g_object_weak_ref (G_OBJECT (client->priv->greeter), + (GWeakNotify) + g_object_unref, + client->priv->connection); + return greeter; + } + + /** + * gdm_client_get_greeter_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmGreeter object that can be used + * to do do various login screen related tasks, such + * as selecting a users session, and starting that + * session. + * + * Returns: (transfer full): #GdmGreeter or %NULL if caller is not a greeter + */ + GdmGreeter * + gdm_client_get_greeter_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { ++ g_autoptr(GDBusConnection) connection = NULL; ++ + if (client->priv->greeter != NULL) { + return g_object_ref (client->priv->greeter); + } + +- if (!gdm_client_open_connection_sync (client, cancellable, error)) { ++ connection = gdm_client_get_connection_sync (client, cancellable, error); ++ ++ if (connection == NULL) { + return NULL; + } + +- client->priv->greeter = gdm_greeter_proxy_new_sync (client->priv->connection, ++ client->priv->greeter = gdm_greeter_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + g_object_weak_ref (G_OBJECT (client->priv->greeter), + (GWeakNotify) + g_object_unref, + client->priv->connection); + + query_for_timed_login_requested_signal (client->priv->greeter); + } + + return client->priv->greeter; + } + + static void + on_remote_greeter_proxy_created (GObject *object, + GAsyncResult *result, + GTask *task) + { + GdmRemoteGreeter *remote_greeter; + GError *error = NULL; + + remote_greeter = gdm_remote_greeter_proxy_new_finish (result, &error); + if (remote_greeter == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + remote_greeter, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + } + + static void +-on_connection_opened_for_remote_greeter (GdmClient *client, +- GAsyncResult *result, +- GTask *task) ++on_connection_for_remote_greeter (GdmClient *client, ++ GAsyncResult *result, ++ GTask *task) + { ++ g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; + GError *error; + + error = NULL; +- if (!gdm_client_open_connection_finish (client, result, &error)) { ++ connection = gdm_client_get_connection_finish (client, result, &error); ++ ++ if (connection == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); +- gdm_remote_greeter_proxy_new (client->priv->connection, ++ gdm_remote_greeter_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + (GAsyncReadyCallback) + on_remote_greeter_proxy_created, + task); + } + + /** + * gdm_client_get_remote_greeter: + * @client: a #GdmClient + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmRemoteGreeter object that can be used to + * verify a user's local account. + */ + void + gdm_client_get_remote_greeter (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->remote_greeter != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->remote_greeter), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + +- gdm_client_open_connection (client, ++ gdm_client_get_connection (client, + cancellable, + (GAsyncReadyCallback) +- on_connection_opened_for_remote_greeter, ++ on_connection_for_remote_greeter, + task); + } + + /** + * gdm_client_get_remote_greeter_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_remote_greeter(). + * + * Returns: (transfer full): a #GdmRemoteGreeter + */ + GdmRemoteGreeter * + gdm_client_get_remote_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmRemoteGreeter *remote_greeter; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->remote_greeter != NULL) + return g_object_ref (client->priv->remote_greeter); + + remote_greeter = g_task_propagate_pointer (G_TASK (result), error); + if (remote_greeter == NULL) + return NULL; + +@@ -1246,253 +1261,266 @@ gdm_client_get_remote_greeter_finish (GdmClient *client, + + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + + g_object_weak_ref (G_OBJECT (client->priv->remote_greeter), + (GWeakNotify) + g_object_unref, + client->priv->connection); + + return remote_greeter; + } + + /** + * gdm_client_get_remote_greeter_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmRemoteGreeter object that can be used + * to do do various remote login screen related tasks, + * such as disconnecting. + * + * Returns: (transfer full): #GdmRemoteGreeter or %NULL if caller is not remote + */ + GdmRemoteGreeter * + gdm_client_get_remote_greeter_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { ++ g_autoptr(GDBusConnection) connection = NULL; ++ + if (client->priv->remote_greeter != NULL) { + return g_object_ref (client->priv->remote_greeter); + } + +- if (!gdm_client_open_connection_sync (client, cancellable, error)) { ++ connection = gdm_client_get_connection_sync (client, cancellable, error); ++ ++ if (connection == NULL) { + return NULL; + } + +- client->priv->remote_greeter = gdm_remote_greeter_proxy_new_sync (client->priv->connection, ++ client->priv->remote_greeter = gdm_remote_greeter_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->remote_greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); ++ g_object_ref (connection); + g_object_weak_ref (G_OBJECT (client->priv->remote_greeter), + (GWeakNotify) + g_object_unref, + client->priv->connection); + } + + return client->priv->remote_greeter; + } + + static void + on_chooser_proxy_created (GObject *source, + GAsyncResult *result, + GTask *task) + { + GdmChooser *chooser; + GError *error = NULL; + + chooser = gdm_chooser_proxy_new_finish (result, &error); + if (chooser == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + chooser, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + } + + static void +-on_connection_opened_for_chooser (GdmClient *client, +- GAsyncResult *result, +- GTask *task) ++on_connection_for_chooser (GdmClient *client, ++ GAsyncResult *result, ++ GTask *task) + { ++ g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; + GError *error; + + error = NULL; +- if (!gdm_client_open_connection_finish (client, result, &error)) { ++ connection = gdm_client_get_connection_finish (client, result, &error); ++ ++ if (connection == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); +- gdm_chooser_proxy_new (client->priv->connection, ++ gdm_chooser_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + (GAsyncReadyCallback) + on_chooser_proxy_created, + task); + } + + /** + * gdm_client_get_chooser: + * @client: a #GdmClient + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmChooser object that can be used to + * verify a user's local account. + */ + void + gdm_client_get_chooser (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->chooser != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->chooser), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + +- gdm_client_open_connection (client, ++ gdm_client_get_connection (client, + cancellable, + (GAsyncReadyCallback) +- on_connection_opened_for_chooser, ++ on_connection_for_chooser, + task); + } + + /** + * gdm_client_get_chooser_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_chooser(). + * + * Returns: (transfer full): a #GdmChooser + */ + GdmChooser * + gdm_client_get_chooser_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmChooser *chooser; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->chooser != NULL) + return g_object_ref (client->priv->chooser); + + chooser = g_task_propagate_pointer (G_TASK (result), error); + if (chooser == NULL) + return NULL; + + client->priv->chooser = chooser; + + g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + ++ g_object_ref (connection); + g_object_weak_ref (G_OBJECT (client->priv->chooser), + (GWeakNotify) + g_object_unref, + client->priv->connection); + + return chooser; + } + + /** + * gdm_client_get_chooser_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmChooser object that can be used + * to do do various XDMCP chooser related tasks, such + * as selecting a host or disconnecting. + * + * Returns: (transfer full): #GdmChooser or %NULL if caller is not a chooser + */ + GdmChooser * + gdm_client_get_chooser_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { ++ g_autoptr(GDBusConnection) connection = NULL; + + if (client->priv->chooser != NULL) { + return g_object_ref (client->priv->chooser); + } + +- if (!gdm_client_open_connection_sync (client, cancellable, error)) { ++ connection = gdm_client_get_connection_sync (client, cancellable, error); ++ ++ if (connection == NULL) { + return NULL; + } + +- client->priv->chooser = gdm_chooser_proxy_new_sync (client->priv->connection, ++ client->priv->chooser = gdm_chooser_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->chooser != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); ++ g_object_ref (connection); + g_object_weak_ref (G_OBJECT (client->priv->chooser), + (GWeakNotify) + g_object_unref, + client->priv->connection); + } + + return client->priv->chooser; + } + + static void + gdm_client_class_init (GdmClientClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gdm_client_finalize; + + g_type_class_add_private (klass, sizeof (GdmClientPrivate)); + + } + + static void + gdm_client_init (GdmClient *client) + { + + client->priv = GDM_CLIENT_GET_PRIVATE (client); + } + + static void + gdm_client_finalize (GObject *object) + { +-- +2.26.2 + diff --git a/SOURCES/0004-libgdm-Drop-weak-refs-on-the-GDBusConnection.patch b/SOURCES/0004-libgdm-Drop-weak-refs-on-the-GDBusConnection.patch new file mode 100644 index 0000000..7886d0b --- /dev/null +++ b/SOURCES/0004-libgdm-Drop-weak-refs-on-the-GDBusConnection.patch @@ -0,0 +1,565 @@ +From 2f3bd5fc3dffd760edd0513c94e8801b36a2bcce Mon Sep 17 00:00:00 2001 +From: Iain Lane +Date: Mon, 14 May 2018 16:32:25 -0400 +Subject: [PATCH 04/15] libgdm: Drop weak refs on the GDBusConnection + +The GDBusProxies hold a strong reference to the connection themselves, +so maintaining separate weak references is unnecessary. + +This commit drops those extraneous weak references. + +https://bugzilla.gnome.org/show_bug.cgi?id=795940 +--- + libgdm/gdm-client.c | 47 --------------------------------------------- + 1 file changed, 47 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index e7b93e382..f327344ec 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -625,67 +625,60 @@ gdm_client_open_reauthentication_channel_sync (GdmClient *client, + username, + &address, + cancellable, + error); + + if (!ret) { + goto out; + } + + g_debug ("GdmClient: connecting to address: %s", client->priv->address); + + connection = g_dbus_connection_new_for_address_sync (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + + if (connection == NULL) { + g_free (address); + goto out; + } + g_free (address); + + user_verifier = gdm_user_verifier_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + +- if (user_verifier != NULL) { +- g_object_weak_ref (G_OBJECT (user_verifier), +- (GWeakNotify) +- g_object_unref, +- connection); +- } +- + out: + return user_verifier; + } + + /** + * gdm_client_open_reauthentication_channel: + * @client: a #GdmClient + * @username: user to reauthenticate + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. + */ + void + gdm_client_open_reauthentication_channel (GdmClient *client, + const char *username, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); +@@ -736,66 +729,60 @@ gdm_client_open_reauthentication_channel_finish (GdmClient *client, + * Returns: (transfer full): #GdmUserVerifier or %NULL if not connected + */ + GdmUserVerifier * + gdm_client_get_user_verifier_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + + if (client->priv->user_verifier != NULL) { + return g_object_ref (client->priv->user_verifier); + } + + connection = gdm_client_get_connection_sync (client, cancellable, error); + + if (connection == NULL) { + return NULL; + } + + client->priv->user_verifier = gdm_user_verifier_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->user_verifier != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); +- g_object_ref (connection); +- g_object_weak_ref (G_OBJECT (client->priv->user_verifier), +- (GWeakNotify) +- g_object_unref, +- client->priv->connection); +- + if (client->priv->enabled_extensions != NULL) { + gboolean res; + + client->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) + free_interface_skeleton); + res = gdm_user_verifier_call_enable_extensions_sync (client->priv->user_verifier, + (const char * const *) + client->priv->enabled_extensions, + cancellable, + NULL); + + if (res) { + size_t i; + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + GdmUserVerifierChoiceList *choice_list_interface; + choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (client->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + NULL); + if (choice_list_interface != NULL) + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], choice_list_interface); + } + } +@@ -881,65 +868,60 @@ gdm_client_get_user_verifier (GdmClient *client, + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_user_verifier(). + * + * Returns: (transfer full): a #GdmUserVerifier + */ + GdmUserVerifier * + gdm_client_get_user_verifier_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmUserVerifier *user_verifier; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->user_verifier != NULL) + return g_object_ref (client->priv->user_verifier); + + user_verifier = g_task_propagate_pointer (G_TASK (result), error); + if (user_verifier == NULL) + return NULL; + + client->priv->user_verifier = user_verifier; + + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + +- g_object_weak_ref (G_OBJECT (client->priv->user_verifier), +- (GWeakNotify) +- g_object_unref, +- client->priv->connection); +- + return user_verifier; + } + + /** + * gdm_client_get_user_verifier_choice_list: + * @client: a #GdmClient + * + * Gets a #GdmUserVerifierChoiceList object that can be used to + * verify a user's local account. + * + * Returns: (transfer none): #GdmUserVerifierChoiceList or %NULL if user + * verifier isn't yet fetched, or daemon doesn't support choice lists + */ + GdmUserVerifierChoiceList * + gdm_client_get_user_verifier_choice_list (GdmClient *client) + { + if (client->priv->user_verifier_extensions == NULL) + return NULL; + + return g_hash_table_lookup (client->priv->user_verifier_extensions, + gdm_user_verifier_choice_list_interface_info ()->name); + } + + static void + on_timed_login_details_got (GdmGreeter *greeter, + GAsyncResult *result) + { + gdm_greeter_call_get_timed_login_details_finish (greeter, NULL, NULL, NULL, result, NULL); + } + +@@ -1054,112 +1036,104 @@ gdm_client_get_greeter (GdmClient *client, + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_greeter(). + * + * Returns: (transfer full): a #GdmGreeter + */ + GdmGreeter * + gdm_client_get_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmGreeter *greeter; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->greeter != NULL) + return g_object_ref (client->priv->greeter); + + greeter = g_task_propagate_pointer (G_TASK (result), error); + if (greeter == NULL) + return NULL; + + client->priv->greeter = greeter; + + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + +- g_object_weak_ref (G_OBJECT (client->priv->greeter), +- (GWeakNotify) +- g_object_unref, +- client->priv->connection); + return greeter; + } + + /** + * gdm_client_get_greeter_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmGreeter object that can be used + * to do do various login screen related tasks, such + * as selecting a users session, and starting that + * session. + * + * Returns: (transfer full): #GdmGreeter or %NULL if caller is not a greeter + */ + GdmGreeter * + gdm_client_get_greeter_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + + if (client->priv->greeter != NULL) { + return g_object_ref (client->priv->greeter); + } + + connection = gdm_client_get_connection_sync (client, cancellable, error); + + if (connection == NULL) { + return NULL; + } + + client->priv->greeter = gdm_greeter_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); +- g_object_weak_ref (G_OBJECT (client->priv->greeter), +- (GWeakNotify) +- g_object_unref, +- client->priv->connection); + + query_for_timed_login_requested_signal (client->priv->greeter); + } + + return client->priv->greeter; + } + + static void + on_remote_greeter_proxy_created (GObject *object, + GAsyncResult *result, + GTask *task) + { + GdmRemoteGreeter *remote_greeter; + GError *error = NULL; + + remote_greeter = gdm_remote_greeter_proxy_new_finish (result, &error); + if (remote_greeter == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + remote_greeter, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + } + + static void + on_connection_for_remote_greeter (GdmClient *client, +@@ -1236,113 +1210,103 @@ gdm_client_get_remote_greeter (GdmClient *client, + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_remote_greeter(). + * + * Returns: (transfer full): a #GdmRemoteGreeter + */ + GdmRemoteGreeter * + gdm_client_get_remote_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmRemoteGreeter *remote_greeter; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->remote_greeter != NULL) + return g_object_ref (client->priv->remote_greeter); + + remote_greeter = g_task_propagate_pointer (G_TASK (result), error); + if (remote_greeter == NULL) + return NULL; + + client->priv->remote_greeter = remote_greeter; + + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + +- g_object_weak_ref (G_OBJECT (client->priv->remote_greeter), +- (GWeakNotify) +- g_object_unref, +- client->priv->connection); +- + return remote_greeter; + } + + /** + * gdm_client_get_remote_greeter_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmRemoteGreeter object that can be used + * to do do various remote login screen related tasks, + * such as disconnecting. + * + * Returns: (transfer full): #GdmRemoteGreeter or %NULL if caller is not remote + */ + GdmRemoteGreeter * + gdm_client_get_remote_greeter_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + + if (client->priv->remote_greeter != NULL) { + return g_object_ref (client->priv->remote_greeter); + } + + connection = gdm_client_get_connection_sync (client, cancellable, error); + + if (connection == NULL) { + return NULL; + } + + client->priv->remote_greeter = gdm_remote_greeter_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->remote_greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); +- g_object_ref (connection); +- g_object_weak_ref (G_OBJECT (client->priv->remote_greeter), +- (GWeakNotify) +- g_object_unref, +- client->priv->connection); + } + + return client->priv->remote_greeter; + } + + static void + on_chooser_proxy_created (GObject *source, + GAsyncResult *result, + GTask *task) + { + GdmChooser *chooser; + GError *error = NULL; + + chooser = gdm_chooser_proxy_new_finish (result, &error); + if (chooser == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + chooser, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + } + + static void + on_connection_for_chooser (GdmClient *client, + GAsyncResult *result, + GTask *task) +@@ -1417,114 +1381,103 @@ gdm_client_get_chooser (GdmClient *client, + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_chooser(). + * + * Returns: (transfer full): a #GdmChooser + */ + GdmChooser * + gdm_client_get_chooser_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmChooser *chooser; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->chooser != NULL) + return g_object_ref (client->priv->chooser); + + chooser = g_task_propagate_pointer (G_TASK (result), error); + if (chooser == NULL) + return NULL; + + client->priv->chooser = chooser; + + g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + +- g_object_ref (connection); +- g_object_weak_ref (G_OBJECT (client->priv->chooser), +- (GWeakNotify) +- g_object_unref, +- client->priv->connection); +- + return chooser; + } + + /** + * gdm_client_get_chooser_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmChooser object that can be used + * to do do various XDMCP chooser related tasks, such + * as selecting a host or disconnecting. + * + * Returns: (transfer full): #GdmChooser or %NULL if caller is not a chooser + */ + GdmChooser * + gdm_client_get_chooser_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + + if (client->priv->chooser != NULL) { + return g_object_ref (client->priv->chooser); + } + + connection = gdm_client_get_connection_sync (client, cancellable, error); + + if (connection == NULL) { + return NULL; + } + + client->priv->chooser = gdm_chooser_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->chooser != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); +- g_object_ref (connection); +- g_object_weak_ref (G_OBJECT (client->priv->chooser), +- (GWeakNotify) +- g_object_unref, +- client->priv->connection); + } + + return client->priv->chooser; + } + + static void + gdm_client_class_init (GdmClientClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gdm_client_finalize; + + g_type_class_add_private (klass, sizeof (GdmClientPrivate)); + + } + + static void + gdm_client_init (GdmClient *client) + { + + client->priv = GDM_CLIENT_GET_PRIVATE (client); + } + + static void + gdm_client_finalize (GObject *object) + { + GdmClient *client; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_CLIENT (object)); +-- +2.26.2 + diff --git a/SOURCES/0005-libgdm-Unref-the-manager-propagated-from-task.patch b/SOURCES/0005-libgdm-Unref-the-manager-propagated-from-task.patch new file mode 100644 index 0000000..54d64f5 --- /dev/null +++ b/SOURCES/0005-libgdm-Unref-the-manager-propagated-from-task.patch @@ -0,0 +1,148 @@ +From 1d4f1675480769618a5595e40c6b459145676ac1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Fri, 1 Jun 2018 17:07:41 +0200 +Subject: [PATCH 05/15] libgdm: Unref the manager propagated from task + +This instance has already been reffed when passed to the task, and since +we're stealing it with `g_task_propagate_pointer` it won't be unreffed. + +We could also do this in the `on_reauthentication_channel_opened` callback +but since the new task will ref it anyway, we can just be clean and do it +here. +--- + libgdm/gdm-client.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index f327344ec..fa4ba8426 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -363,61 +363,61 @@ on_reauthentication_channel_opened (GdmManager *manager, + on_reauthentication_channel_connected, + task); + } + + static void + on_got_manager_for_reauthentication (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + char *username; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + username = g_object_get_data (G_OBJECT (task), "username"); + gdm_manager_call_open_reauthentication_channel (manager, + username, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_opened, + task); +- ++ g_object_unref (manager); + } + + static GDBusConnection * + gdm_client_get_connection_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GdmManager) manager = NULL; + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + if (client->priv->connection != NULL) { + return g_object_ref (client->priv->connection); + } + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + goto out; + } + + ret = gdm_manager_call_open_session_sync (manager, + &client->priv->address, + cancellable, +@@ -500,60 +500,62 @@ on_session_opened (GdmManager *manager, + cancellable, + (GAsyncReadyCallback) + on_connected, + task); + g_object_unref (client); + } + + static void + on_got_manager_for_opening_connection (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_manager_call_open_session (manager, + cancellable, + (GAsyncReadyCallback) + on_session_opened, + task); ++ ++ g_object_unref (manager); + } + + static GDBusConnection * + gdm_client_get_connection_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GDBusConnection *connection = NULL; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { + return NULL; + } + + if (client->priv->connection == NULL) { + client->priv->connection = connection; + g_object_add_weak_pointer (G_OBJECT (client->priv->connection), + (gpointer *) &client->priv->connection); + } + + return g_object_ref (connection); + } + + static void + gdm_client_get_connection (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +-- +2.26.2 + diff --git a/SOURCES/0006-libgdm-Don-t-double-ref-the-connection-got-from-task.patch b/SOURCES/0006-libgdm-Don-t-double-ref-the-connection-got-from-task.patch new file mode 100644 index 0000000..08dd061 --- /dev/null +++ b/SOURCES/0006-libgdm-Don-t-double-ref-the-connection-got-from-task.patch @@ -0,0 +1,100 @@ +From bcf04c4b6ae1543fd3f0d11b8c0f7907c1a0e14a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Fri, 1 Jun 2018 17:16:35 +0200 +Subject: [PATCH 06/15] libgdm: Don't double-ref the connection got from task + +Both if we re-use the shared connection in `gdm_client_get_connection` and if +we create a new one in `on_connected`, we steal the pointer here by using +`g_task_propagate_pointer` and thus we don't have to add an additional +reference to this connection when returning, or it won't ever be consumed by +function customers. +--- + libgdm/gdm-client.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index fa4ba8426..36292148c 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -509,76 +509,76 @@ on_got_manager_for_opening_connection (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_manager_call_open_session (manager, + cancellable, + (GAsyncReadyCallback) + on_session_opened, + task); + + g_object_unref (manager); + } + + static GDBusConnection * + gdm_client_get_connection_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { +- GDBusConnection *connection = NULL; ++ GDBusConnection *connection; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { + return NULL; + } + + if (client->priv->connection == NULL) { + client->priv->connection = connection; + g_object_add_weak_pointer (G_OBJECT (client->priv->connection), + (gpointer *) &client->priv->connection); + } + +- return g_object_ref (connection); ++ return connection; + } + + static void + gdm_client_get_connection (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->connection != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->connection), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + + get_manager (client, + cancellable, + (GAsyncReadyCallback) + on_got_manager_for_opening_connection, + task); +-- +2.26.2 + diff --git a/SOURCES/0007-libgdm-Don-t-leak-connection-on-sync-re-authenticati.patch b/SOURCES/0007-libgdm-Don-t-leak-connection-on-sync-re-authenticati.patch new file mode 100644 index 0000000..dc06760 --- /dev/null +++ b/SOURCES/0007-libgdm-Don-t-leak-connection-on-sync-re-authenticati.patch @@ -0,0 +1,79 @@ +From 9f4e892308ef99eaf0153357f9940a7174473d06 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Fri, 1 Jun 2018 17:20:17 +0200 +Subject: [PATCH 07/15] libgdm: Don't leak connection on sync re-authentication + +--- + libgdm/gdm-client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index 36292148c..335a040a2 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -577,61 +577,61 @@ gdm_client_get_connection (GdmClient *client, + return; + } + + get_manager (client, + cancellable, + (GAsyncReadyCallback) + on_got_manager_for_opening_connection, + task); + } + + /** + * gdm_client_open_reauthentication_channel_sync: + * @client: a #GdmClient + * @username: user to reauthenticate + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. Free with + * g_object_unref to close reauthentication channel. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not + * already logged in. + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_sync (GdmClient *client, + const char *username, + GCancellable *cancellable, + GError **error) + { +- GDBusConnection *connection; ++ g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GdmManager) manager = NULL; + GdmUserVerifier *user_verifier = NULL; + gboolean ret; + char *address; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + goto out; + } + + ret = gdm_manager_call_open_reauthentication_channel_sync (manager, + username, + &address, + cancellable, + error); + + if (!ret) { + goto out; + } + + g_debug ("GdmClient: connecting to address: %s", client->priv->address); + +-- +2.26.2 + diff --git a/SOURCES/0008-libgdm-Use-auto-pointers-and-cleanup-code.patch b/SOURCES/0008-libgdm-Use-auto-pointers-and-cleanup-code.patch new file mode 100644 index 0000000..d6f83a2 --- /dev/null +++ b/SOURCES/0008-libgdm-Use-auto-pointers-and-cleanup-code.patch @@ -0,0 +1,131 @@ +From 4a22da5123f3097fa0e3fff82a5b556b0f021f7b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Fri, 1 Jun 2018 17:22:20 +0200 +Subject: [PATCH 08/15] libgdm: Use auto-pointers and cleanup code + +--- + libgdm/gdm-client.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index 335a040a2..7b42b6c99 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -579,109 +579,106 @@ gdm_client_get_connection (GdmClient *client, + + get_manager (client, + cancellable, + (GAsyncReadyCallback) + on_got_manager_for_opening_connection, + task); + } + + /** + * gdm_client_open_reauthentication_channel_sync: + * @client: a #GdmClient + * @username: user to reauthenticate + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. Free with + * g_object_unref to close reauthentication channel. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not + * already logged in. + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_sync (GdmClient *client, + const char *username, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GdmManager) manager = NULL; ++ g_autofree char *address = NULL; + GdmUserVerifier *user_verifier = NULL; + gboolean ret; +- char *address; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { +- goto out; ++ return NULL; + } + + ret = gdm_manager_call_open_reauthentication_channel_sync (manager, + username, + &address, + cancellable, + error); + + if (!ret) { +- goto out; ++ return NULL; + } + +- g_debug ("GdmClient: connecting to address: %s", client->priv->address); ++ g_debug ("GdmClient: connecting to address: %s", address); + + connection = g_dbus_connection_new_for_address_sync (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + + if (connection == NULL) { +- g_free (address); +- goto out; ++ return NULL; + } +- g_free (address); + + user_verifier = gdm_user_verifier_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + +- out: + return user_verifier; + } + + /** + * gdm_client_open_reauthentication_channel: + * @client: a #GdmClient + * @username: user to reauthenticate + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. + */ + void + gdm_client_open_reauthentication_channel (GdmClient *client, + const char *username, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + +-- +2.26.2 + diff --git a/SOURCES/0009-libgdb-Try-to-reuse-connections-from-the-available-p.patch b/SOURCES/0009-libgdb-Try-to-reuse-connections-from-the-available-p.patch new file mode 100644 index 0000000..21a5822 --- /dev/null +++ b/SOURCES/0009-libgdb-Try-to-reuse-connections-from-the-available-p.patch @@ -0,0 +1,475 @@ +From 3701174621efd15d06dcfccdca6e5aa8d2a37e41 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Sat, 2 Jun 2018 19:34:08 +0200 +Subject: [PATCH 09/15] libgdb: Try to reuse connections from the available + proxies + +Instead of using the hard-to-maintain shared pointer to the dbus connection +to the manager and reset it when the proxies that use it are deleted, just +look which proxy is currently available and try to reuse the connection +from it. + +Fixes #386 +--- + libgdm/gdm-client.c | 70 +++++++++++++++++++++++++-------------------- + 1 file changed, 39 insertions(+), 31 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index 7b42b6c99..acf016a48 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -19,85 +19,106 @@ + * + */ + + #include "config.h" + + #include + #include + #include + #include + + #include + #include + #include + + #include "gdm-client.h" + #include "gdm-client-glue.h" + #include "gdm-manager-glue.h" + + #define GDM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CLIENT, GdmClientPrivate)) + + #define SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session" + + struct GdmClientPrivate + { + GdmUserVerifier *user_verifier; + GHashTable *user_verifier_extensions; + + GdmGreeter *greeter; + GdmRemoteGreeter *remote_greeter; + GdmChooser *chooser; +- GDBusConnection *connection; + char *address; + + char **enabled_extensions; + }; + + static void gdm_client_class_init (GdmClientClass *klass); + static void gdm_client_init (GdmClient *client); + static void gdm_client_finalize (GObject *object); + + G_DEFINE_TYPE (GdmClient, gdm_client, G_TYPE_OBJECT); + + static gpointer client_object = NULL; + + GQuark + gdm_client_error_quark (void) + { + static GQuark error_quark = 0; + + if (error_quark == 0) + error_quark = g_quark_from_static_string ("gdm-client"); + + return error_quark; + } + ++static GDBusConnection * ++gdm_client_get_open_connection (GdmClient *client) ++{ ++ GDBusProxy *proxy = NULL; ++ ++ if (client->priv->user_verifier != NULL) { ++ proxy = G_DBUS_PROXY (client->priv->user_verifier); ++ } else if (client->priv->greeter != NULL) { ++ proxy = G_DBUS_PROXY (client->priv->greeter); ++ } else if (client->priv->remote_greeter != NULL) { ++ proxy = G_DBUS_PROXY (client->priv->remote_greeter); ++ } else if (client->priv->chooser != NULL) { ++ proxy = G_DBUS_PROXY (client->priv->chooser); ++ } ++ ++ if (proxy != NULL) { ++ return g_dbus_proxy_get_connection (proxy); ++ } ++ ++ return NULL; ++} ++ + static void + on_got_manager (GObject *object, + GAsyncResult *result, + GTask *task) + { + GdmClient *client; + GError *error; + g_autoptr(GdmManager) manager = NULL; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); + + error = NULL; + manager = gdm_manager_proxy_new_finish (result, &error); + + if (error != NULL) { + g_task_return_error (task, error); + } else { + g_task_return_pointer (task, + g_object_ref (manager), + (GDestroyNotify) g_object_unref); + } + + g_object_unref (task); + g_object_unref (client); + } + + static void + get_manager (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, +@@ -372,107 +393,106 @@ on_got_manager_for_reauthentication (GdmClient *client, + GCancellable *cancellable; + GdmManager *manager; + char *username; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + username = g_object_get_data (G_OBJECT (task), "username"); + gdm_manager_call_open_reauthentication_channel (manager, + username, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_opened, + task); + g_object_unref (manager); + } + + static GDBusConnection * + gdm_client_get_connection_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GdmManager) manager = NULL; ++ GDBusConnection *connection; + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + +- if (client->priv->connection != NULL) { +- return g_object_ref (client->priv->connection); ++ connection = gdm_client_get_open_connection (client); ++ ++ if (connection != NULL) { ++ return g_object_ref (connection); + } + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + goto out; + } + + ret = gdm_manager_call_open_session_sync (manager, + &client->priv->address, + cancellable, + error); + + if (!ret) { + goto out; + } + + g_debug ("GdmClient: connecting to address: %s", client->priv->address); + +- client->priv->connection = g_dbus_connection_new_for_address_sync (client->priv->address, +- G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, +- NULL, +- cancellable, +- error); ++ connection = g_dbus_connection_new_for_address_sync (client->priv->address, ++ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, ++ NULL, ++ cancellable, ++ error); + +- if (client->priv->connection == NULL) { ++ if (connection == NULL) { + g_clear_pointer (&client->priv->address, g_free); + goto out; + } + +- g_object_add_weak_pointer (G_OBJECT (client->priv->connection), +- (gpointer *) +- &client->priv->connection); +- + out: +- return client->priv->connection; ++ return connection; + } + + static void + on_connected (GObject *source_object, + GAsyncResult *result, + GTask *task) + { + GDBusConnection *connection; + GError *error; + + error = NULL; + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (!connection) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + g_object_ref (connection), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + g_object_unref (connection); + } + + static void + on_session_opened (GdmManager *manager, + GAsyncResult *result, + GTask *task) + { +@@ -518,87 +538,83 @@ on_got_manager_for_opening_connection (GdmClient *client, + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_manager_call_open_session (manager, + cancellable, + (GAsyncReadyCallback) + on_session_opened, + task); + + g_object_unref (manager); + } + + static GDBusConnection * + gdm_client_get_connection_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GDBusConnection *connection; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { + return NULL; + } + +- if (client->priv->connection == NULL) { +- client->priv->connection = connection; +- g_object_add_weak_pointer (G_OBJECT (client->priv->connection), +- (gpointer *) &client->priv->connection); +- } +- + return connection; + } + + static void + gdm_client_get_connection (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; ++ GDBusConnection *connection; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + +- if (client->priv->connection != NULL) { ++ connection = gdm_client_get_open_connection (client); ++ if (connection != NULL) { + g_task_return_pointer (task, +- g_object_ref (client->priv->connection), ++ g_object_ref (connection), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + + get_manager (client, + cancellable, + (GAsyncReadyCallback) + on_got_manager_for_opening_connection, + task); + } + + /** + * gdm_client_open_reauthentication_channel_sync: + * @client: a #GdmClient + * @username: user to reauthenticate + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. Free with + * g_object_unref to close reauthentication channel. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not + * already logged in. + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_sync (GdmClient *client, + const char *username, + GCancellable *cancellable, +@@ -748,61 +764,61 @@ gdm_client_get_user_verifier_sync (GdmClient *client, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->user_verifier != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + if (client->priv->enabled_extensions != NULL) { + gboolean res; + + client->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) + free_interface_skeleton); + res = gdm_user_verifier_call_enable_extensions_sync (client->priv->user_verifier, + (const char * const *) + client->priv->enabled_extensions, + cancellable, + NULL); + + if (res) { + size_t i; + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + GdmUserVerifierChoiceList *choice_list_interface; +- choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (client->priv->connection, ++ choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + NULL); + if (choice_list_interface != NULL) + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], choice_list_interface); + } + } + } + } + } + + return client->priv->user_verifier; + } + + static void + on_connection_for_user_verifier (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; + GError *error; + + error = NULL; + connection = gdm_client_get_connection_finish (client, result, &error); + + if (connection == NULL) { + g_task_return_error (task, error); +@@ -1482,68 +1498,60 @@ gdm_client_finalize (GObject *object) + g_return_if_fail (GDM_IS_CLIENT (object)); + + client = GDM_CLIENT (object); + + g_return_if_fail (client->priv != NULL); + + if (client->priv->user_verifier != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + } + + if (client->priv->greeter != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + } + + if (client->priv->remote_greeter != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + } + + if (client->priv->chooser != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + } + +- if (client->priv->connection != NULL) { +- g_object_remove_weak_pointer (G_OBJECT (client->priv->connection), +- (gpointer *) +- &client->priv->connection); +- } +- +- g_clear_object (&client->priv->connection); +- + g_strfreev (client->priv->enabled_extensions); + g_free (client->priv->address); + + G_OBJECT_CLASS (gdm_client_parent_class)->finalize (object); + } + + GdmClient * + gdm_client_new (void) + { + if (client_object != NULL) { + g_object_ref (client_object); + } else { + client_object = g_object_new (GDM_TYPE_CLIENT, NULL); + g_object_add_weak_pointer (client_object, + (gpointer *) &client_object); + } + + return GDM_CLIENT (client_object); + } + + + /** + * gdm_client_set_enabled_extensions: + * @client: a #GdmClient + * @extensions: (array zero-terminated=1) (element-type utf8): a list of extensions + * + * Enables GDM's pam extensions. Currently, only + * org.gnome.DisplayManager.UserVerifier.ChoiceList is supported. + */ + void +-- +2.26.2 + diff --git a/SOURCES/0010-libgdm-Don-t-save-manager-address.patch b/SOURCES/0010-libgdm-Don-t-save-manager-address.patch new file mode 100644 index 0000000..d095f09 --- /dev/null +++ b/SOURCES/0010-libgdm-Don-t-save-manager-address.patch @@ -0,0 +1,307 @@ +From 3e1801ab06d7dec11c8a038d1e46cf260bf8c0c5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Sat, 2 Jun 2018 19:44:24 +0200 +Subject: [PATCH 10/15] libgdm: Don't save manager address + +There's no need to keep the manager connection address around, and +use autofree to clean it up +--- + libgdm/gdm-client.c | 24 +++++++++--------------- + 1 file changed, 9 insertions(+), 15 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index acf016a48..0e8bf4399 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -19,61 +19,60 @@ + * + */ + + #include "config.h" + + #include + #include + #include + #include + + #include + #include + #include + + #include "gdm-client.h" + #include "gdm-client-glue.h" + #include "gdm-manager-glue.h" + + #define GDM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CLIENT, GdmClientPrivate)) + + #define SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session" + + struct GdmClientPrivate + { + GdmUserVerifier *user_verifier; + GHashTable *user_verifier_extensions; + + GdmGreeter *greeter; + GdmRemoteGreeter *remote_greeter; + GdmChooser *chooser; +- char *address; + + char **enabled_extensions; + }; + + static void gdm_client_class_init (GdmClientClass *klass); + static void gdm_client_init (GdmClient *client); + static void gdm_client_finalize (GObject *object); + + G_DEFINE_TYPE (GdmClient, gdm_client, G_TYPE_OBJECT); + + static gpointer client_object = NULL; + + GQuark + gdm_client_error_quark (void) + { + static GQuark error_quark = 0; + + if (error_quark == 0) + error_quark = g_quark_from_static_string ("gdm-client"); + + return error_quark; + } + + static GDBusConnection * + gdm_client_get_open_connection (GdmClient *client) + { + GDBusProxy *proxy = NULL; + + if (client->priv->user_verifier != NULL) { + proxy = G_DBUS_PROXY (client->priv->user_verifier); +@@ -393,155 +392,151 @@ on_got_manager_for_reauthentication (GdmClient *client, + GCancellable *cancellable; + GdmManager *manager; + char *username; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + username = g_object_get_data (G_OBJECT (task), "username"); + gdm_manager_call_open_reauthentication_channel (manager, + username, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_opened, + task); + g_object_unref (manager); + } + + static GDBusConnection * + gdm_client_get_connection_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GdmManager) manager = NULL; ++ g_autofree char *address = NULL; + GDBusConnection *connection; + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); + + connection = gdm_client_get_open_connection (client); + + if (connection != NULL) { + return g_object_ref (connection); + } + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { +- goto out; ++ return NULL; + } + + ret = gdm_manager_call_open_session_sync (manager, +- &client->priv->address, ++ &address, + cancellable, + error); + + if (!ret) { +- goto out; ++ return NULL; + } + +- g_debug ("GdmClient: connecting to address: %s", client->priv->address); ++ g_debug ("GdmClient: connecting to address: %s", address); + +- connection = g_dbus_connection_new_for_address_sync (client->priv->address, ++ connection = g_dbus_connection_new_for_address_sync (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + +- if (connection == NULL) { +- g_clear_pointer (&client->priv->address, g_free); +- goto out; +- } +- +- out: + return connection; + } + + static void + on_connected (GObject *source_object, + GAsyncResult *result, + GTask *task) + { + GDBusConnection *connection; + GError *error; + + error = NULL; + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (!connection) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + g_object_ref (connection), + (GDestroyNotify) g_object_unref); + g_object_unref (task); + g_object_unref (connection); + } + + static void + on_session_opened (GdmManager *manager, + GAsyncResult *result, + GTask *task) + { + GdmClient *client; ++ g_autofree char *address = NULL; + GCancellable *cancellable; + GError *error; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); + + error = NULL; + if (!gdm_manager_call_open_session_finish (manager, +- &client->priv->address, ++ &address, + result, + &error)) { + g_task_return_error (task, error); + g_object_unref (task); + g_object_unref (client); + return; + } + + cancellable = g_task_get_cancellable (task); +- g_dbus_connection_new_for_address (client->priv->address, ++ g_dbus_connection_new_for_address (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + (GAsyncReadyCallback) + on_connected, + task); + g_object_unref (client); + } + + static void + on_got_manager_for_opening_connection (GdmClient *client, + GAsyncResult *result, + GTask *task) + { + GCancellable *cancellable; + GdmManager *manager; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_manager_call_open_session (manager, + cancellable, + (GAsyncReadyCallback) +@@ -1499,61 +1494,60 @@ gdm_client_finalize (GObject *object) + + client = GDM_CLIENT (object); + + g_return_if_fail (client->priv != NULL); + + if (client->priv->user_verifier != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + } + + if (client->priv->greeter != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + } + + if (client->priv->remote_greeter != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + } + + if (client->priv->chooser != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + } + + g_strfreev (client->priv->enabled_extensions); +- g_free (client->priv->address); + + G_OBJECT_CLASS (gdm_client_parent_class)->finalize (object); + } + + GdmClient * + gdm_client_new (void) + { + if (client_object != NULL) { + g_object_ref (client_object); + } else { + client_object = g_object_new (GDM_TYPE_CLIENT, NULL); + g_object_add_weak_pointer (client_object, + (gpointer *) &client_object); + } + + return GDM_CLIENT (client_object); + } + + + /** + * gdm_client_set_enabled_extensions: + * @client: a #GdmClient + * @extensions: (array zero-terminated=1) (element-type utf8): a list of extensions + * + * Enables GDM's pam extensions. Currently, only + * org.gnome.DisplayManager.UserVerifier.ChoiceList is supported. + */ + void + gdm_client_set_enabled_extensions (GdmClient *client, + const char * const *extensions) +-- +2.26.2 + diff --git a/SOURCES/0011-libgdm-Return-NULL-on-invalid-client-instances.patch b/SOURCES/0011-libgdm-Return-NULL-on-invalid-client-instances.patch new file mode 100644 index 0000000..d29b2bf --- /dev/null +++ b/SOURCES/0011-libgdm-Return-NULL-on-invalid-client-instances.patch @@ -0,0 +1,520 @@ +From b6bb149d03c7c979ced0652f0b464dc147743c64 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Mon, 4 Jun 2018 19:13:04 +0200 +Subject: [PATCH 11/15] libgdm: Return NULL on invalid client instances + +--- + libgdm/gdm-client.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index 0e8bf4399..28cb72536 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -396,61 +396,61 @@ on_got_manager_for_reauthentication (GdmClient *client, + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + username = g_object_get_data (G_OBJECT (task), "username"); + gdm_manager_call_open_reauthentication_channel (manager, + username, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_opened, + task); + g_object_unref (manager); + } + + static GDBusConnection * + gdm_client_get_connection_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GdmManager) manager = NULL; + g_autofree char *address = NULL; + GDBusConnection *connection; + gboolean ret; + +- g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); ++ g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + connection = gdm_client_get_open_connection (client); + + if (connection != NULL) { + return g_object_ref (connection); + } + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + return NULL; + } + + ret = gdm_manager_call_open_session_sync (manager, + &address, + cancellable, + error); + + if (!ret) { + return NULL; + } + + g_debug ("GdmClient: connecting to address: %s", address); + + connection = g_dbus_connection_new_for_address_sync (address, +@@ -526,61 +526,61 @@ on_got_manager_for_opening_connection (GdmClient *client, + { + GCancellable *cancellable; + GdmManager *manager; + GError *error; + + error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_manager_call_open_session (manager, + cancellable, + (GAsyncReadyCallback) + on_session_opened, + task); + + g_object_unref (manager); + } + + static GDBusConnection * + gdm_client_get_connection_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GDBusConnection *connection; + +- g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); ++ g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { + return NULL; + } + + return connection; + } + + static void + gdm_client_get_connection (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + GDBusConnection *connection; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + connection = gdm_client_get_open_connection (client); + if (connection != NULL) { + g_task_return_pointer (task, + g_object_ref (connection), + (GDestroyNotify) g_object_unref); +@@ -594,61 +594,61 @@ gdm_client_get_connection (GdmClient *client, + on_got_manager_for_opening_connection, + task); + } + + /** + * gdm_client_open_reauthentication_channel_sync: + * @client: a #GdmClient + * @username: user to reauthenticate + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. Free with + * g_object_unref to close reauthentication channel. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not + * already logged in. + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_sync (GdmClient *client, + const char *username, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GdmManager) manager = NULL; + g_autofree char *address = NULL; + GdmUserVerifier *user_verifier = NULL; + gboolean ret; + +- g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); ++ g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + return NULL; + } + + ret = gdm_manager_call_open_reauthentication_channel_sync (manager, + username, + &address, + cancellable, + error); + + if (!ret) { + return NULL; + } + + g_debug ("GdmClient: connecting to address: %s", address); + + connection = g_dbus_connection_new_for_address_sync (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + +@@ -695,61 +695,61 @@ gdm_client_open_reauthentication_channel (GdmClient *client, + + g_object_set_data_full (G_OBJECT (task), + "username", + g_strdup (username), + (GDestroyNotify) + g_free); + + get_manager (client, + cancellable, + (GAsyncReadyCallback) + on_got_manager_for_reauthentication, + task); + } + + /** + * gdm_client_open_reauthentication_channel_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_open_reauthentication_channel(). + * + * Returns: (transfer full): a #GdmUserVerifier + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { +- g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); ++ g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + return g_task_propagate_pointer (G_TASK (result), error); + } + + /** + * gdm_client_get_user_verifier_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * verify a user's local account. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if not connected + */ + GdmUserVerifier * + gdm_client_get_user_verifier_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + + if (client->priv->user_verifier != NULL) { + return g_object_ref (client->priv->user_verifier); + } + + connection = gdm_client_get_connection_sync (client, cancellable, error); + + if (connection == NULL) { + return NULL; +@@ -863,61 +863,61 @@ gdm_client_get_user_verifier (GdmClient *client, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + + gdm_client_get_connection (client, + cancellable, + (GAsyncReadyCallback) + on_connection_for_user_verifier, + task); + } + + /** + * gdm_client_get_user_verifier_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_user_verifier(). + * + * Returns: (transfer full): a #GdmUserVerifier + */ + GdmUserVerifier * + gdm_client_get_user_verifier_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmUserVerifier *user_verifier; + +- g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); ++ g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->user_verifier != NULL) + return g_object_ref (client->priv->user_verifier); + + user_verifier = g_task_propagate_pointer (G_TASK (result), error); + if (user_verifier == NULL) + return NULL; + + client->priv->user_verifier = user_verifier; + + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + + return user_verifier; + } + + /** + * gdm_client_get_user_verifier_choice_list: + * @client: a #GdmClient + * + * Gets a #GdmUserVerifierChoiceList object that can be used to + * verify a user's local account. + * + * Returns: (transfer none): #GdmUserVerifierChoiceList or %NULL if user + * verifier isn't yet fetched, or daemon doesn't support choice lists + */ + GdmUserVerifierChoiceList * + gdm_client_get_user_verifier_choice_list (GdmClient *client) + { +@@ -1031,61 +1031,61 @@ gdm_client_get_greeter (GdmClient *client, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + + gdm_client_get_connection (client, + cancellable, + (GAsyncReadyCallback) + on_connection_for_greeter, + task); + } + + /** + * gdm_client_get_greeter_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_greeter(). + * + * Returns: (transfer full): a #GdmGreeter + */ + GdmGreeter * + gdm_client_get_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmGreeter *greeter; + +- g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); ++ g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->greeter != NULL) + return g_object_ref (client->priv->greeter); + + greeter = g_task_propagate_pointer (G_TASK (result), error); + if (greeter == NULL) + return NULL; + + client->priv->greeter = greeter; + + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + + return greeter; + } + + /** + * gdm_client_get_greeter_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmGreeter object that can be used + * to do do various login screen related tasks, such + * as selecting a users session, and starting that + * session. + * + * Returns: (transfer full): #GdmGreeter or %NULL if caller is not a greeter + */ +@@ -1205,61 +1205,61 @@ gdm_client_get_remote_greeter (GdmClient *client, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + + gdm_client_get_connection (client, + cancellable, + (GAsyncReadyCallback) + on_connection_for_remote_greeter, + task); + } + + /** + * gdm_client_get_remote_greeter_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_remote_greeter(). + * + * Returns: (transfer full): a #GdmRemoteGreeter + */ + GdmRemoteGreeter * + gdm_client_get_remote_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmRemoteGreeter *remote_greeter; + +- g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); ++ g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->remote_greeter != NULL) + return g_object_ref (client->priv->remote_greeter); + + remote_greeter = g_task_propagate_pointer (G_TASK (result), error); + if (remote_greeter == NULL) + return NULL; + + client->priv->remote_greeter = remote_greeter; + + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + + return remote_greeter; + } + + /** + * gdm_client_get_remote_greeter_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmRemoteGreeter object that can be used + * to do do various remote login screen related tasks, + * such as disconnecting. + * + * Returns: (transfer full): #GdmRemoteGreeter or %NULL if caller is not remote + */ + GdmRemoteGreeter * +@@ -1376,61 +1376,61 @@ gdm_client_get_chooser (GdmClient *client, + (GDestroyNotify) g_object_unref); + g_object_unref (task); + return; + } + + gdm_client_get_connection (client, + cancellable, + (GAsyncReadyCallback) + on_connection_for_chooser, + task); + } + + /** + * gdm_client_get_chooser_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_chooser(). + * + * Returns: (transfer full): a #GdmChooser + */ + GdmChooser * + gdm_client_get_chooser_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmChooser *chooser; + +- g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE); ++ g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->chooser != NULL) + return g_object_ref (client->priv->chooser); + + chooser = g_task_propagate_pointer (G_TASK (result), error); + if (chooser == NULL) + return NULL; + + client->priv->chooser = chooser; + + g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + + return chooser; + } + + /** + * gdm_client_get_chooser_sync: + * @client: a #GdmClient + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmChooser object that can be used + * to do do various XDMCP chooser related tasks, such + * as selecting a host or disconnecting. + * + * Returns: (transfer full): #GdmChooser or %NULL if caller is not a chooser + */ + GdmChooser * +-- +2.26.2 + diff --git a/SOURCES/0012-libgdm-use-g_autoptr-to-manage-objects-lifecycle.patch b/SOURCES/0012-libgdm-use-g_autoptr-to-manage-objects-lifecycle.patch new file mode 100644 index 0000000..3380077 --- /dev/null +++ b/SOURCES/0012-libgdm-use-g_autoptr-to-manage-objects-lifecycle.patch @@ -0,0 +1,1275 @@ +From 1ea98ce63ec43236c7da96ffb613127a8cf8910c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Mon, 4 Jun 2018 19:11:25 +0200 +Subject: [PATCH 12/15] libgdm: use g_autoptr to manage objects lifecycle + +Using auto pointers allows to manage things in a cleaner way without having +to manually unref things before returning. +--- + libgdm/gdm-client.c | 264 +++++++++++++++++++------------------------- + 1 file changed, 111 insertions(+), 153 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index 28cb72536..f9e3faee2 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -67,102 +67,97 @@ gdm_client_error_quark (void) + error_quark = g_quark_from_static_string ("gdm-client"); + + return error_quark; + } + + static GDBusConnection * + gdm_client_get_open_connection (GdmClient *client) + { + GDBusProxy *proxy = NULL; + + if (client->priv->user_verifier != NULL) { + proxy = G_DBUS_PROXY (client->priv->user_verifier); + } else if (client->priv->greeter != NULL) { + proxy = G_DBUS_PROXY (client->priv->greeter); + } else if (client->priv->remote_greeter != NULL) { + proxy = G_DBUS_PROXY (client->priv->remote_greeter); + } else if (client->priv->chooser != NULL) { + proxy = G_DBUS_PROXY (client->priv->chooser); + } + + if (proxy != NULL) { + return g_dbus_proxy_get_connection (proxy); + } + + return NULL; + } + + static void + on_got_manager (GObject *object, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { +- GdmClient *client; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GdmClient) client = NULL; + g_autoptr(GdmManager) manager = NULL; ++ g_autoptr(GError) error = NULL; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); +- +- error = NULL; + manager = gdm_manager_proxy_new_finish (result, &error); + + if (error != NULL) { +- g_task_return_error (task, error); ++ g_task_return_error (task, g_steal_pointer (&error)); + } else { + g_task_return_pointer (task, +- g_object_ref (manager), ++ g_steal_pointer (&manager), + (GDestroyNotify) g_object_unref); + } +- +- g_object_unref (task); +- g_object_unref (client); + } + + static void + get_manager (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + GTask *task; + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + gdm_manager_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, +- (GAsyncReadyCallback) + on_got_manager, + task); + } + + typedef struct { + GTask *task; + GdmUserVerifier *user_verifier; + } UserVerifierData; + + static UserVerifierData * + user_verifier_data_new (GTask *task, GdmUserVerifier *user_verifier) + { + UserVerifierData *data; + + data = g_slice_new (UserVerifierData); + data->task = g_object_ref (task); + data->user_verifier = g_object_ref (user_verifier); + + return data; + } + + static void + user_verifier_data_free (UserVerifierData *data) + { + g_object_unref (data->task); + g_object_unref (data->user_verifier); + g_slice_free (UserVerifierData, data); + } + + static void +@@ -173,477 +168,455 @@ complete_user_verifier_proxy_operation (GdmClient *client, + g_object_ref (data->user_verifier), + (GDestroyNotify) g_object_unref); + user_verifier_data_free (data); + } + + static void + maybe_complete_user_verifier_proxy_operation (GdmClient *client, + UserVerifierData *data) + { + GHashTableIter iter; + gpointer key, value; + + if (client->priv->user_verifier_extensions != NULL) { + g_hash_table_iter_init (&iter, client->priv->user_verifier_extensions); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (value == NULL) + return; + } + } + + complete_user_verifier_proxy_operation (client, data); + } + + static void + on_user_verifier_choice_list_proxy_created (GObject *source, + GAsyncResult *result, + UserVerifierData *data) + { + GdmClient *client; + GdmUserVerifierChoiceList *choice_list; +- GError *error = NULL; ++ g_autoptr(GError) error = NULL; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (data->task))); + + choice_list = gdm_user_verifier_choice_list_proxy_new_finish (result, &error); + + if (choice_list == NULL) { + g_debug ("Couldn't create UserVerifier ChoiceList proxy: %s", error->message); +- g_clear_error (&error); + g_hash_table_remove (client->priv->user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name); + } else { + g_hash_table_replace (client->priv->user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name, choice_list); + } + + maybe_complete_user_verifier_proxy_operation (client, data); + } + + static void + on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, + GAsyncResult *result, + UserVerifierData *data) + { + GdmClient *client; + GCancellable *cancellable; + GDBusConnection *connection; +- GError *error = NULL; ++ g_autoptr(GError) error = NULL; + size_t i; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (data->task))); + cancellable = g_task_get_cancellable (data->task); + + gdm_user_verifier_call_enable_extensions_finish (user_verifier, result, &error); + + if (error != NULL) { + g_debug ("Couldn't enable user verifier extensions: %s", + error->message); +- g_clear_error (&error); + complete_user_verifier_proxy_operation (client, data); + return; + } + + connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (user_verifier)); + + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + g_debug ("Enabled extensions[%lu] = %s", i, client->priv->enabled_extensions[i]); + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], NULL); + + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], NULL); + gdm_user_verifier_choice_list_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + (GAsyncReadyCallback) + on_user_verifier_choice_list_proxy_created, + data); + } else { + g_debug ("User verifier extension %s is unsupported", client->priv->enabled_extensions[i]); + g_hash_table_remove (client->priv->user_verifier_extensions, + client->priv->enabled_extensions[i]); + } + } + + if (g_hash_table_size (client->priv->user_verifier_extensions) == 0) { + g_debug ("No supported user verifier extensions"); + complete_user_verifier_proxy_operation (client, data); + } + + } + + static void + free_interface_skeleton (GDBusInterfaceSkeleton *interface) + { + if (interface == NULL) + return; + + g_object_unref (interface); + } + + static void + on_user_verifier_proxy_created (GObject *source, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { + GdmClient *self; +- GdmUserVerifier *user_verifier; + GCancellable *cancellable = NULL; +- GError *error = NULL; ++ g_autoptr(GdmUserVerifier) user_verifier = NULL; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; + + user_verifier = gdm_user_verifier_proxy_new_finish (result, &error); + if (user_verifier == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + g_debug ("UserVerifier %p created", user_verifier); + + self = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); + if (self->priv->enabled_extensions == NULL) { + g_debug ("no enabled extensions"); + g_task_return_pointer (task, +- user_verifier, ++ g_steal_pointer (&user_verifier), + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + return; + } + + self->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) + free_interface_skeleton); + cancellable = g_task_get_cancellable (task); + gdm_user_verifier_call_enable_extensions (user_verifier, + (const char * const *) + self->priv->enabled_extensions, + cancellable, + (GAsyncReadyCallback) + on_user_verifier_extensions_enabled, + user_verifier_data_new (task, user_verifier)); +- g_object_unref (user_verifier); + } + + static void + on_reauthentication_channel_connected (GObject *source_object, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { +- GDBusConnection *connection; + GCancellable *cancellable; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GDBusConnection) connection = NULL; ++ g_autoptr(GError) error = NULL; + +- error = NULL; + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (!connection) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_user_verifier_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, +- (GAsyncReadyCallback) + on_user_verifier_proxy_created, +- task); +- g_object_unref (connection); ++ g_steal_pointer (&task)); + } + + static void + on_reauthentication_channel_opened (GdmManager *manager, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { + GCancellable *cancellable; +- char *address; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ g_autofree char *address = NULL; + +- error = NULL; + if (!gdm_manager_call_open_reauthentication_channel_finish (manager, + &address, + result, + &error)) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + g_dbus_connection_new_for_address (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, +- (GAsyncReadyCallback) + on_reauthentication_channel_connected, +- task); ++ g_steal_pointer (&task)); + } + + static void + on_got_manager_for_reauthentication (GdmClient *client, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { + GCancellable *cancellable; +- GdmManager *manager; +- char *username; +- GError *error; ++ const char *username; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GdmManager) manager = NULL; ++ g_autoptr(GError) error = NULL; + +- error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + username = g_object_get_data (G_OBJECT (task), "username"); + gdm_manager_call_open_reauthentication_channel (manager, + username, + cancellable, + (GAsyncReadyCallback) + on_reauthentication_channel_opened, +- task); +- g_object_unref (manager); ++ g_steal_pointer (&task)); + } + + static GDBusConnection * + gdm_client_get_connection_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GdmManager) manager = NULL; + g_autofree char *address = NULL; + GDBusConnection *connection; + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + connection = gdm_client_get_open_connection (client); + + if (connection != NULL) { + return g_object_ref (connection); + } + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + return NULL; + } + + ret = gdm_manager_call_open_session_sync (manager, + &address, + cancellable, + error); + + if (!ret) { + return NULL; + } + + g_debug ("GdmClient: connecting to address: %s", address); + + connection = g_dbus_connection_new_for_address_sync (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + + return connection; + } + + static void + on_connected (GObject *source_object, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { +- GDBusConnection *connection; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GDBusConnection) connection = NULL; ++ g_autoptr(GError) error = NULL; + +- error = NULL; + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (!connection) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + g_task_return_pointer (task, +- g_object_ref (connection), ++ g_steal_pointer (&connection), + (GDestroyNotify) g_object_unref); +- g_object_unref (task); +- g_object_unref (connection); + } + + static void + on_session_opened (GdmManager *manager, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { +- GdmClient *client; +- g_autofree char *address = NULL; + GCancellable *cancellable; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GdmClient) client = NULL; ++ g_autoptr(GError) error = NULL; ++ g_autofree char *address = NULL; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); + +- error = NULL; + if (!gdm_manager_call_open_session_finish (manager, + &address, + result, + &error)) { +- g_task_return_error (task, error); +- g_object_unref (task); +- g_object_unref (client); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + g_dbus_connection_new_for_address (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, +- (GAsyncReadyCallback) + on_connected, +- task); +- g_object_unref (client); ++ g_steal_pointer (&task)); + } + + static void + on_got_manager_for_opening_connection (GdmClient *client, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { + GCancellable *cancellable; +- GdmManager *manager; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GdmManager) manager = NULL; ++ g_autoptr(GError) error = NULL; + +- error = NULL; + manager = g_task_propagate_pointer (G_TASK (result), &error); + if (manager == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_manager_call_open_session (manager, + cancellable, + (GAsyncReadyCallback) + on_session_opened, +- task); +- +- g_object_unref (manager); ++ g_steal_pointer (&task)); + } + + static GDBusConnection * + gdm_client_get_connection_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GDBusConnection *connection; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { + return NULL; + } + + return connection; + } + + static void + gdm_client_get_connection (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { +- GTask *task; ++ g_autoptr(GTask) task = NULL; + GDBusConnection *connection; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + connection = gdm_client_get_open_connection (client); + if (connection != NULL) { + g_task_return_pointer (task, + g_object_ref (connection), + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + return; + } + + get_manager (client, + cancellable, + (GAsyncReadyCallback) + on_got_manager_for_opening_connection, +- task); ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_open_reauthentication_channel_sync: + * @client: a #GdmClient + * @username: user to reauthenticate + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. Free with + * g_object_unref to close reauthentication channel. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not + * already logged in. + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_sync (GdmClient *client, + const char *username, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; +- g_autoptr(GdmManager) manager = NULL; ++ g_autoptr(GdmManager) manager = NULL; + g_autofree char *address = NULL; + GdmUserVerifier *user_verifier = NULL; + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + return NULL; + } + + ret = gdm_manager_call_open_reauthentication_channel_sync (manager, + username, + &address, + cancellable, + error); + + if (!ret) { + return NULL; + } + + g_debug ("GdmClient: connecting to address: %s", address); + + connection = g_dbus_connection_new_for_address_sync (address, +@@ -779,124 +752,120 @@ gdm_client_get_user_verifier_sync (GdmClient *client, + client->priv->enabled_extensions, + cancellable, + NULL); + + if (res) { + size_t i; + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + GdmUserVerifierChoiceList *choice_list_interface; + choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + NULL); + if (choice_list_interface != NULL) + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], choice_list_interface); + } + } + } + } + } + + return client->priv->user_verifier; + } + + static void + on_connection_for_user_verifier (GdmClient *client, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { +- g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GDBusConnection) connection = NULL; ++ g_autoptr(GError) error = NULL; + +- error = NULL; + connection = gdm_client_get_connection_finish (client, result, &error); +- + if (connection == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_user_verifier_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, +- (GAsyncReadyCallback) + on_user_verifier_proxy_created, +- task); ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_get_user_verifier: + * @client: a #GdmClient + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmUserVerifier object that can be used to + * verify a user's local account. + */ + void + gdm_client_get_user_verifier (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { +- GTask *task; ++ g_autoptr(GTask) task = NULL; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->user_verifier != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->user_verifier), + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + return; + } + + gdm_client_get_connection (client, +- cancellable, +- (GAsyncReadyCallback) +- on_connection_for_user_verifier, +- task); ++ cancellable, ++ (GAsyncReadyCallback) ++ on_connection_for_user_verifier, ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_get_user_verifier_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_user_verifier(). + * + * Returns: (transfer full): a #GdmUserVerifier + */ + GdmUserVerifier * + gdm_client_get_user_verifier_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmUserVerifier *user_verifier; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->user_verifier != NULL) + return g_object_ref (client->priv->user_verifier); + + user_verifier = g_task_propagate_pointer (G_TASK (result), error); + if (user_verifier == NULL) + return NULL; + + client->priv->user_verifier = user_verifier; +@@ -924,147 +893,143 @@ gdm_client_get_user_verifier_choice_list (GdmClient *client) + if (client->priv->user_verifier_extensions == NULL) + return NULL; + + return g_hash_table_lookup (client->priv->user_verifier_extensions, + gdm_user_verifier_choice_list_interface_info ()->name); + } + + static void + on_timed_login_details_got (GdmGreeter *greeter, + GAsyncResult *result) + { + gdm_greeter_call_get_timed_login_details_finish (greeter, NULL, NULL, NULL, result, NULL); + } + + static void + query_for_timed_login_requested_signal (GdmGreeter *greeter) + { + /* This just makes sure a timed-login-requested signal gets fired + * off if appropriate. + */ + gdm_greeter_call_get_timed_login_details (greeter, + NULL, + (GAsyncReadyCallback) + on_timed_login_details_got, + NULL); + } + + static void + on_greeter_proxy_created (GObject *source, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; + GdmGreeter *greeter; +- GError *error = NULL; + + greeter = gdm_greeter_proxy_new_finish (result, &error); + if (greeter == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + g_task_return_pointer (task, + greeter, + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + + query_for_timed_login_requested_signal (greeter); + } + + static void + on_connection_for_greeter (GdmClient *client, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { +- g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GDBusConnection) connection = NULL; ++ g_autoptr(GError) error = NULL; + +- error = NULL; + connection = gdm_client_get_connection_finish (client, result, &error); + + if (connection == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_greeter_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, +- (GAsyncReadyCallback) + on_greeter_proxy_created, +- task); ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_get_greeter: + * @client: a #GdmClient + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmGreeter object that can be used to + * verify a user's local account. + */ + void + gdm_client_get_greeter (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { +- GTask *task; ++ g_autoptr(GTask) task = NULL; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->greeter != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->greeter), + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + return; + } + + gdm_client_get_connection (client, +- cancellable, +- (GAsyncReadyCallback) +- on_connection_for_greeter, +- task); ++ cancellable, ++ (GAsyncReadyCallback) ++ on_connection_for_greeter, ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_get_greeter_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_greeter(). + * + * Returns: (transfer full): a #GdmGreeter + */ + GdmGreeter * + gdm_client_get_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmGreeter *greeter; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->greeter != NULL) + return g_object_ref (client->priv->greeter); + + greeter = g_task_propagate_pointer (G_TASK (result), error); + if (greeter == NULL) + return NULL; + + client->priv->greeter = greeter; +@@ -1100,145 +1065,141 @@ gdm_client_get_greeter_sync (GdmClient *client, + return g_object_ref (client->priv->greeter); + } + + connection = gdm_client_get_connection_sync (client, cancellable, error); + + if (connection == NULL) { + return NULL; + } + + client->priv->greeter = gdm_greeter_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + + query_for_timed_login_requested_signal (client->priv->greeter); + } + + return client->priv->greeter; + } + + static void + on_remote_greeter_proxy_created (GObject *object, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; + GdmRemoteGreeter *remote_greeter; +- GError *error = NULL; + + remote_greeter = gdm_remote_greeter_proxy_new_finish (result, &error); + if (remote_greeter == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + g_task_return_pointer (task, + remote_greeter, + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + } + + static void + on_connection_for_remote_greeter (GdmClient *client, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { +- g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GDBusConnection) connection = NULL; ++ g_autoptr(GError) error = NULL; + +- error = NULL; + connection = gdm_client_get_connection_finish (client, result, &error); + + if (connection == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_remote_greeter_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, +- (GAsyncReadyCallback) + on_remote_greeter_proxy_created, +- task); ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_get_remote_greeter: + * @client: a #GdmClient + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmRemoteGreeter object that can be used to + * verify a user's local account. + */ + void + gdm_client_get_remote_greeter (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { +- GTask *task; ++ g_autoptr (GTask) task = NULL; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->remote_greeter != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->remote_greeter), + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + return; + } + + gdm_client_get_connection (client, +- cancellable, +- (GAsyncReadyCallback) +- on_connection_for_remote_greeter, +- task); ++ cancellable, ++ (GAsyncReadyCallback) ++ on_connection_for_remote_greeter, ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_get_remote_greeter_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_remote_greeter(). + * + * Returns: (transfer full): a #GdmRemoteGreeter + */ + GdmRemoteGreeter * + gdm_client_get_remote_greeter_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmRemoteGreeter *remote_greeter; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->remote_greeter != NULL) + return g_object_ref (client->priv->remote_greeter); + + remote_greeter = g_task_propagate_pointer (G_TASK (result), error); + if (remote_greeter == NULL) + return NULL; + + client->priv->remote_greeter = remote_greeter; +@@ -1271,145 +1232,142 @@ gdm_client_get_remote_greeter_sync (GdmClient *client, + + if (client->priv->remote_greeter != NULL) { + return g_object_ref (client->priv->remote_greeter); + } + + connection = gdm_client_get_connection_sync (client, cancellable, error); + + if (connection == NULL) { + return NULL; + } + + client->priv->remote_greeter = gdm_remote_greeter_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->remote_greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + } + + return client->priv->remote_greeter; + } + + static void + on_chooser_proxy_created (GObject *source, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { + GdmChooser *chooser; +- GError *error = NULL; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; + + chooser = gdm_chooser_proxy_new_finish (result, &error); + if (chooser == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + g_task_return_pointer (task, + chooser, + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + } + + static void + on_connection_for_chooser (GdmClient *client, + GAsyncResult *result, +- GTask *task) ++ gpointer user_data) + { +- g_autoptr(GDBusConnection) connection = NULL; + GCancellable *cancellable; +- GError *error; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GDBusConnection) connection = NULL; ++ g_autoptr(GError) error = NULL; + +- error = NULL; + connection = gdm_client_get_connection_finish (client, result, &error); + + if (connection == NULL) { +- g_task_return_error (task, error); +- g_object_unref (task); ++ g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_chooser_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + (GAsyncReadyCallback) + on_chooser_proxy_created, +- task); ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_get_chooser: + * @client: a #GdmClient + * @callback: a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback + * @cancellable: a #GCancellable + * + * Gets a #GdmChooser object that can be used to + * verify a user's local account. + */ + void + gdm_client_get_chooser (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { +- GTask *task; ++ g_autoptr(GTask) task = NULL; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + + if (client->priv->chooser != NULL) { + g_task_return_pointer (task, + g_object_ref (client->priv->chooser), + (GDestroyNotify) g_object_unref); +- g_object_unref (task); + return; + } + + gdm_client_get_connection (client, +- cancellable, +- (GAsyncReadyCallback) +- on_connection_for_chooser, +- task); ++ cancellable, ++ (GAsyncReadyCallback) ++ on_connection_for_chooser, ++ g_steal_pointer (&task)); + } + + /** + * gdm_client_get_chooser_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_chooser(). + * + * Returns: (transfer full): a #GdmChooser + */ + GdmChooser * + gdm_client_get_chooser_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmChooser *chooser; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->chooser != NULL) + return g_object_ref (client->priv->chooser); + + chooser = g_task_propagate_pointer (G_TASK (result), error); + if (chooser == NULL) + return NULL; + + client->priv->chooser = chooser; +-- +2.26.2 + diff --git a/SOURCES/0013-libgdm-Fix-client-leaks-from-g_async_result_get_sour.patch b/SOURCES/0013-libgdm-Fix-client-leaks-from-g_async_result_get_sour.patch new file mode 100644 index 0000000..2e36a05 --- /dev/null +++ b/SOURCES/0013-libgdm-Fix-client-leaks-from-g_async_result_get_sour.patch @@ -0,0 +1,172 @@ +From 3651eeda8e7c1fb324c84ff9d87d4981dfd6e50f Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 27 Sep 2020 01:06:37 -0400 +Subject: [PATCH 13/15] libgdm: Fix client leaks from + g_async_result_get_source_object + +There are are few places in the code where the client object is +retrieved via g_async_result_get_source_object. Those calls +return a fresh reference that is never unreferenced later. + +This commit plugs those leaks by using g_autoptr's +--- + libgdm/gdm-client.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index f9e3faee2..66f6102ec 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -166,84 +166,84 @@ complete_user_verifier_proxy_operation (GdmClient *client, + { + g_task_return_pointer (data->task, + g_object_ref (data->user_verifier), + (GDestroyNotify) g_object_unref); + user_verifier_data_free (data); + } + + static void + maybe_complete_user_verifier_proxy_operation (GdmClient *client, + UserVerifierData *data) + { + GHashTableIter iter; + gpointer key, value; + + if (client->priv->user_verifier_extensions != NULL) { + g_hash_table_iter_init (&iter, client->priv->user_verifier_extensions); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (value == NULL) + return; + } + } + + complete_user_verifier_proxy_operation (client, data); + } + + static void + on_user_verifier_choice_list_proxy_created (GObject *source, + GAsyncResult *result, + UserVerifierData *data) + { +- GdmClient *client; ++ g_autoptr(GdmClient) client = NULL; + GdmUserVerifierChoiceList *choice_list; + g_autoptr(GError) error = NULL; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (data->task))); + + choice_list = gdm_user_verifier_choice_list_proxy_new_finish (result, &error); + + if (choice_list == NULL) { + g_debug ("Couldn't create UserVerifier ChoiceList proxy: %s", error->message); + g_hash_table_remove (client->priv->user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name); + } else { + g_hash_table_replace (client->priv->user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name, choice_list); + } + + maybe_complete_user_verifier_proxy_operation (client, data); + } + + static void + on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, + GAsyncResult *result, + UserVerifierData *data) + { +- GdmClient *client; ++ g_autoptr(GdmClient) client = NULL; + GCancellable *cancellable; + GDBusConnection *connection; + g_autoptr(GError) error = NULL; + size_t i; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (data->task))); + cancellable = g_task_get_cancellable (data->task); + + gdm_user_verifier_call_enable_extensions_finish (user_verifier, result, &error); + + if (error != NULL) { + g_debug ("Couldn't enable user verifier extensions: %s", + error->message); + complete_user_verifier_proxy_operation (client, data); + return; + } + + connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (user_verifier)); + + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + g_debug ("Enabled extensions[%lu] = %s", i, client->priv->enabled_extensions[i]); + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], NULL); + + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], NULL); + gdm_user_verifier_choice_list_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, +@@ -252,61 +252,61 @@ on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, + on_user_verifier_choice_list_proxy_created, + data); + } else { + g_debug ("User verifier extension %s is unsupported", client->priv->enabled_extensions[i]); + g_hash_table_remove (client->priv->user_verifier_extensions, + client->priv->enabled_extensions[i]); + } + } + + if (g_hash_table_size (client->priv->user_verifier_extensions) == 0) { + g_debug ("No supported user verifier extensions"); + complete_user_verifier_proxy_operation (client, data); + } + + } + + static void + free_interface_skeleton (GDBusInterfaceSkeleton *interface) + { + if (interface == NULL) + return; + + g_object_unref (interface); + } + + static void + on_user_verifier_proxy_created (GObject *source, + GAsyncResult *result, + gpointer user_data) + { +- GdmClient *self; ++ g_autoptr(GdmClient) self = NULL; + GCancellable *cancellable = NULL; + g_autoptr(GdmUserVerifier) user_verifier = NULL; + g_autoptr(GTask) task = user_data; + g_autoptr(GError) error = NULL; + + user_verifier = gdm_user_verifier_proxy_new_finish (result, &error); + if (user_verifier == NULL) { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + g_debug ("UserVerifier %p created", user_verifier); + + self = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); + if (self->priv->enabled_extensions == NULL) { + g_debug ("no enabled extensions"); + g_task_return_pointer (task, + g_steal_pointer (&user_verifier), + (GDestroyNotify) g_object_unref); + return; + } + + self->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) + free_interface_skeleton); + cancellable = g_task_get_cancellable (task); + gdm_user_verifier_call_enable_extensions (user_verifier, + (const char * const *) +-- +2.26.2 + diff --git a/SOURCES/0014-libgdm-Fetch-connection-synchronously.patch b/SOURCES/0014-libgdm-Fetch-connection-synchronously.patch new file mode 100644 index 0000000..acb2330 --- /dev/null +++ b/SOURCES/0014-libgdm-Fetch-connection-synchronously.patch @@ -0,0 +1,214 @@ +From 1974c64e7611d737d354dc9cb57a8a266e179e84 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 11 Oct 2020 21:36:44 -0400 +Subject: [PATCH 14/15] libgdm: Fetch connection synchronously + +There's a race condition in the client connection code at the moment, +where a user verifier could be waiting for its connection when the login +screen asks for a greeter synchronously. The greeter will then end up +with a different connection that the user verifier which breaks +expectations. + +This commit just makes the connection fetching code synchronous for now +to side step the problem. +--- + libgdm/gdm-client.c | 94 +++++---------------------------------------- + 1 file changed, 9 insertions(+), 85 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index 66f6102ec..afe78087f 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -419,180 +419,104 @@ gdm_client_get_connection_sync (GdmClient *client, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.DisplayManager", + "/org/gnome/DisplayManager/Manager", + cancellable, + error); + + if (manager == NULL) { + return NULL; + } + + ret = gdm_manager_call_open_session_sync (manager, + &address, + cancellable, + error); + + if (!ret) { + return NULL; + } + + g_debug ("GdmClient: connecting to address: %s", address); + + connection = g_dbus_connection_new_for_address_sync (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + error); + + return connection; + } + +-static void +-on_connected (GObject *source_object, +- GAsyncResult *result, +- gpointer user_data) +-{ +- g_autoptr(GTask) task = user_data; +- g_autoptr(GDBusConnection) connection = NULL; +- g_autoptr(GError) error = NULL; +- +- connection = g_dbus_connection_new_for_address_finish (result, &error); +- if (!connection) { +- g_task_return_error (task, g_steal_pointer (&error)); +- return; +- } +- +- g_task_return_pointer (task, +- g_steal_pointer (&connection), +- (GDestroyNotify) g_object_unref); +-} +- +-static void +-on_session_opened (GdmManager *manager, +- GAsyncResult *result, +- gpointer user_data) +-{ +- GCancellable *cancellable; +- g_autoptr(GTask) task = user_data; +- g_autoptr(GdmClient) client = NULL; +- g_autoptr(GError) error = NULL; +- g_autofree char *address = NULL; +- +- client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); +- +- if (!gdm_manager_call_open_session_finish (manager, +- &address, +- result, +- &error)) { +- g_task_return_error (task, g_steal_pointer (&error)); +- return; +- } +- +- cancellable = g_task_get_cancellable (task); +- g_dbus_connection_new_for_address (address, +- G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, +- NULL, +- cancellable, +- on_connected, +- g_steal_pointer (&task)); +-} +- +-static void +-on_got_manager_for_opening_connection (GdmClient *client, +- GAsyncResult *result, +- gpointer user_data) +-{ +- GCancellable *cancellable; +- g_autoptr(GTask) task = user_data; +- g_autoptr(GdmManager) manager = NULL; +- g_autoptr(GError) error = NULL; +- +- manager = g_task_propagate_pointer (G_TASK (result), &error); +- if (manager == NULL) { +- g_task_return_error (task, g_steal_pointer (&error)); +- return; +- } +- +- cancellable = g_task_get_cancellable (task); +- gdm_manager_call_open_session (manager, +- cancellable, +- (GAsyncReadyCallback) +- on_session_opened, +- g_steal_pointer (&task)); +-} +- + static GDBusConnection * + gdm_client_get_connection_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GDBusConnection *connection; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + connection = g_task_propagate_pointer (G_TASK (result), error); + if (connection == NULL) { + return NULL; + } + + return connection; + } + + static void + gdm_client_get_connection (GdmClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) + { + g_autoptr(GTask) task = NULL; ++ g_autoptr(GError) error = NULL; + GDBusConnection *connection; + + g_return_if_fail (GDM_IS_CLIENT (client)); + + task = g_task_new (G_OBJECT (client), + cancellable, + callback, + user_data); + +- connection = gdm_client_get_open_connection (client); ++ connection = gdm_client_get_connection_sync (client, ++ cancellable, ++ &error); + if (connection != NULL) { +- g_task_return_pointer (task, +- g_object_ref (connection), +- (GDestroyNotify) g_object_unref); +- return; ++ g_task_return_pointer (task, ++ g_object_ref (connection), ++ (GDestroyNotify) g_object_unref); ++ } else { ++ g_task_return_error (task, g_steal_pointer (&error)); + } +- +- get_manager (client, +- cancellable, +- (GAsyncReadyCallback) +- on_got_manager_for_opening_connection, +- g_steal_pointer (&task)); + } + + /** + * gdm_client_open_reauthentication_channel_sync: + * @client: a #GdmClient + * @username: user to reauthenticate + * @cancellable: a #GCancellable + * @error: a #GError + * + * Gets a #GdmUserVerifier object that can be used to + * reauthenticate an already logged in user. Free with + * g_object_unref to close reauthentication channel. + * + * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not + * already logged in. + */ + GdmUserVerifier * + gdm_client_open_reauthentication_channel_sync (GdmClient *client, + const char *username, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GdmManager) manager = NULL; + g_autofree char *address = NULL; + GdmUserVerifier *user_verifier = NULL; + gboolean ret; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + +-- +2.26.2 + diff --git a/SOURCES/0015-libgdm-Don-t-leak-user-verifier-extensions-on-unlock.patch b/SOURCES/0015-libgdm-Don-t-leak-user-verifier-extensions-on-unlock.patch new file mode 100644 index 0000000..b9b4de9 --- /dev/null +++ b/SOURCES/0015-libgdm-Don-t-leak-user-verifier-extensions-on-unlock.patch @@ -0,0 +1,439 @@ +From 760810cd751c8a511b4eb58c0159fef1163f7355 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 25 Sep 2020 15:27:47 -0400 +Subject: [PATCH 15/15] libgdm: Don't leak user verifier extensions on unlock + +GdmClient fails to free the hash table associated with user +verifier extensions when the client is done with the user verifier. + +This commit ties the user verifier extensions to the user verifier +instance associated with it, instead of storing the extensions +directly in the client struct. +--- + libgdm/gdm-client.c | 70 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 48 insertions(+), 22 deletions(-) + +diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c +index afe78087f..752961227 100644 +--- a/libgdm/gdm-client.c ++++ b/libgdm/gdm-client.c +@@ -147,193 +147,204 @@ user_verifier_data_new (GTask *task, GdmUserVerifier *user_verifier) + + data = g_slice_new (UserVerifierData); + data->task = g_object_ref (task); + data->user_verifier = g_object_ref (user_verifier); + + return data; + } + + static void + user_verifier_data_free (UserVerifierData *data) + { + g_object_unref (data->task); + g_object_unref (data->user_verifier); + g_slice_free (UserVerifierData, data); + } + + static void + complete_user_verifier_proxy_operation (GdmClient *client, + UserVerifierData *data) + { + g_task_return_pointer (data->task, + g_object_ref (data->user_verifier), + (GDestroyNotify) g_object_unref); + user_verifier_data_free (data); + } + + static void + maybe_complete_user_verifier_proxy_operation (GdmClient *client, + UserVerifierData *data) + { ++ GHashTable *user_verifier_extensions; + GHashTableIter iter; + gpointer key, value; + +- if (client->priv->user_verifier_extensions != NULL) { +- g_hash_table_iter_init (&iter, client->priv->user_verifier_extensions); ++ user_verifier_extensions = g_object_get_data (G_OBJECT (client->priv->user_verifier), "gdm-client-user-verifier-extensions"); ++ if (user_verifier_extensions != NULL) { ++ g_hash_table_iter_init (&iter, user_verifier_extensions); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (value == NULL) + return; + } + } + + complete_user_verifier_proxy_operation (client, data); + } + + static void + on_user_verifier_choice_list_proxy_created (GObject *source, + GAsyncResult *result, + UserVerifierData *data) + { ++ GHashTable *user_verifier_extensions; + g_autoptr(GdmClient) client = NULL; + GdmUserVerifierChoiceList *choice_list; + g_autoptr(GError) error = NULL; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (data->task))); + ++ user_verifier_extensions = g_object_get_data (G_OBJECT (data->user_verifier), "gdm-client-user-verifier-extensions"); + choice_list = gdm_user_verifier_choice_list_proxy_new_finish (result, &error); + + if (choice_list == NULL) { + g_debug ("Couldn't create UserVerifier ChoiceList proxy: %s", error->message); +- g_hash_table_remove (client->priv->user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name); ++ g_hash_table_remove (user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name); + } else { +- g_hash_table_replace (client->priv->user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name, choice_list); ++ g_hash_table_replace (user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name, choice_list); + } + + maybe_complete_user_verifier_proxy_operation (client, data); + } + + static void + on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, + GAsyncResult *result, + UserVerifierData *data) + { + g_autoptr(GdmClient) client = NULL; ++ GHashTable *user_verifier_extensions; + GCancellable *cancellable; + GDBusConnection *connection; + g_autoptr(GError) error = NULL; + size_t i; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (data->task))); + cancellable = g_task_get_cancellable (data->task); ++ user_verifier_extensions = g_object_get_data (G_OBJECT (user_verifier), "gdm-client-user-verifier-extensions"); + + gdm_user_verifier_call_enable_extensions_finish (user_verifier, result, &error); + + if (error != NULL) { + g_debug ("Couldn't enable user verifier extensions: %s", + error->message); + complete_user_verifier_proxy_operation (client, data); + return; + } + + connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (user_verifier)); + + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + g_debug ("Enabled extensions[%lu] = %s", i, client->priv->enabled_extensions[i]); +- g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], NULL); ++ g_hash_table_insert (user_verifier_extensions, client->priv->enabled_extensions[i], NULL); + + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { +- g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], NULL); ++ g_hash_table_insert (user_verifier_extensions, client->priv->enabled_extensions[i], NULL); + gdm_user_verifier_choice_list_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + (GAsyncReadyCallback) + on_user_verifier_choice_list_proxy_created, + data); + } else { + g_debug ("User verifier extension %s is unsupported", client->priv->enabled_extensions[i]); +- g_hash_table_remove (client->priv->user_verifier_extensions, ++ g_hash_table_remove (user_verifier_extensions, + client->priv->enabled_extensions[i]); + } + } + +- if (g_hash_table_size (client->priv->user_verifier_extensions) == 0) { ++ if (g_hash_table_size (user_verifier_extensions) == 0) { + g_debug ("No supported user verifier extensions"); + complete_user_verifier_proxy_operation (client, data); + } + + } + + static void + free_interface_skeleton (GDBusInterfaceSkeleton *interface) + { + if (interface == NULL) + return; + + g_object_unref (interface); + } + + static void + on_user_verifier_proxy_created (GObject *source, + GAsyncResult *result, + gpointer user_data) + { + g_autoptr(GdmClient) self = NULL; ++ GHashTable *user_verifier_extensions; + GCancellable *cancellable = NULL; + g_autoptr(GdmUserVerifier) user_verifier = NULL; + g_autoptr(GTask) task = user_data; + g_autoptr(GError) error = NULL; + + user_verifier = gdm_user_verifier_proxy_new_finish (result, &error); + if (user_verifier == NULL) { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + g_debug ("UserVerifier %p created", user_verifier); + + self = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); + if (self->priv->enabled_extensions == NULL) { + g_debug ("no enabled extensions"); + g_task_return_pointer (task, + g_steal_pointer (&user_verifier), + (GDestroyNotify) g_object_unref); + return; + } + +- self->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, +- g_str_equal, +- NULL, +- (GDestroyNotify) +- free_interface_skeleton); ++ user_verifier_extensions = g_hash_table_new_full (g_str_hash, ++ g_str_equal, ++ NULL, ++ (GDestroyNotify) ++ free_interface_skeleton); ++ g_object_set_data_full (G_OBJECT (user_verifier), ++ "gdm-client-user-verifier-extensions", ++ user_verifier_extensions, ++ (GDestroyNotify) g_hash_table_unref); + cancellable = g_task_get_cancellable (task); + gdm_user_verifier_call_enable_extensions (user_verifier, + (const char * const *) + self->priv->enabled_extensions, + cancellable, + (GAsyncReadyCallback) + on_user_verifier_extensions_enabled, + user_verifier_data_new (task, user_verifier)); + } + + static void + on_reauthentication_channel_connected (GObject *source_object, + GAsyncResult *result, + gpointer user_data) + { + GCancellable *cancellable; + g_autoptr(GTask) task = user_data; + g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GError) error = NULL; + + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (!connection) { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_user_verifier_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, +@@ -637,87 +648,93 @@ gdm_client_open_reauthentication_channel_finish (GdmClient *client, + */ + GdmUserVerifier * + gdm_client_get_user_verifier_sync (GdmClient *client, + GCancellable *cancellable, + GError **error) + { + g_autoptr(GDBusConnection) connection = NULL; + + if (client->priv->user_verifier != NULL) { + return g_object_ref (client->priv->user_verifier); + } + + connection = gdm_client_get_connection_sync (client, cancellable, error); + + if (connection == NULL) { + return NULL; + } + + client->priv->user_verifier = gdm_user_verifier_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + error); + + if (client->priv->user_verifier != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + if (client->priv->enabled_extensions != NULL) { ++ GHashTable *user_verifier_extensions; + gboolean res; + +- client->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, +- g_str_equal, +- NULL, +- (GDestroyNotify) +- free_interface_skeleton); ++ user_verifier_extensions = g_hash_table_new_full (g_str_hash, ++ g_str_equal, ++ NULL, ++ (GDestroyNotify) ++ free_interface_skeleton); ++ g_object_set_data_full (G_OBJECT (client->priv->user_verifier), ++ "gdm-client-user-verifier-extensions", ++ user_verifier_extensions, ++ (GDestroyNotify) g_hash_table_unref); ++ + res = gdm_user_verifier_call_enable_extensions_sync (client->priv->user_verifier, + (const char * const *) + client->priv->enabled_extensions, + cancellable, + NULL); + + if (res) { + size_t i; + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + GdmUserVerifierChoiceList *choice_list_interface; + choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + NULL); + if (choice_list_interface != NULL) +- g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], choice_list_interface); ++ g_hash_table_insert (user_verifier_extensions, client->priv->enabled_extensions[i], choice_list_interface); + } + } + } + } + } + + return client->priv->user_verifier; + } + + static void + on_connection_for_user_verifier (GdmClient *client, + GAsyncResult *result, + gpointer user_data) + { + GCancellable *cancellable; + g_autoptr(GTask) task = user_data; + g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GError) error = NULL; + + connection = gdm_client_get_connection_finish (client, result, &error); + if (connection == NULL) { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cancellable = g_task_get_cancellable (task); + gdm_user_verifier_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, +@@ -765,86 +782,95 @@ gdm_client_get_user_verifier (GdmClient *client, + g_steal_pointer (&task)); + } + + /** + * gdm_client_get_user_verifier_finish: + * @client: a #GdmClient + * @result: The #GAsyncResult from the callback + * @error: a #GError + * + * Finishes an operation started with + * gdm_client_get_user_verifier(). + * + * Returns: (transfer full): a #GdmUserVerifier + */ + GdmUserVerifier * + gdm_client_get_user_verifier_finish (GdmClient *client, + GAsyncResult *result, + GError **error) + { + GdmUserVerifier *user_verifier; + + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); + + if (client->priv->user_verifier != NULL) + return g_object_ref (client->priv->user_verifier); + + user_verifier = g_task_propagate_pointer (G_TASK (result), error); + if (user_verifier == NULL) + return NULL; + +- client->priv->user_verifier = user_verifier; ++ if (client->priv->user_verifier != NULL) { ++ g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier), ++ (gpointer *) ++ &client->priv->user_verifier); ++ } + + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + ++ client->priv->user_verifier = user_verifier; ++ + return user_verifier; + } + + /** + * gdm_client_get_user_verifier_choice_list: + * @client: a #GdmClient + * + * Gets a #GdmUserVerifierChoiceList object that can be used to + * verify a user's local account. + * + * Returns: (transfer none): #GdmUserVerifierChoiceList or %NULL if user + * verifier isn't yet fetched, or daemon doesn't support choice lists + */ + GdmUserVerifierChoiceList * + gdm_client_get_user_verifier_choice_list (GdmClient *client) + { +- if (client->priv->user_verifier_extensions == NULL) ++ GHashTable *user_verifier_extensions; ++ ++ user_verifier_extensions = g_object_get_data (G_OBJECT (client->priv->user_verifier), "gdm-client-user-verifier-extensions"); ++ if (user_verifier_extensions == NULL) + return NULL; + +- return g_hash_table_lookup (client->priv->user_verifier_extensions, ++ return g_hash_table_lookup (user_verifier_extensions, + gdm_user_verifier_choice_list_interface_info ()->name); + } + + static void + on_timed_login_details_got (GdmGreeter *greeter, + GAsyncResult *result) + { + gdm_greeter_call_get_timed_login_details_finish (greeter, NULL, NULL, NULL, result, NULL); + } + + static void + query_for_timed_login_requested_signal (GdmGreeter *greeter) + { + /* This just makes sure a timed-login-requested signal gets fired + * off if appropriate. + */ + gdm_greeter_call_get_timed_login_details (greeter, + NULL, + (GAsyncReadyCallback) + on_timed_login_details_got, + NULL); + } + + static void + on_greeter_proxy_created (GObject *source, + GAsyncResult *result, + gpointer user_data) + { + g_autoptr(GTask) task = user_data; + g_autoptr(GError) error = NULL; +-- +2.26.2 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index b4dca99..26a6a15 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -10,7 +10,7 @@ Name: gdm Epoch: 1 Version: 3.28.2 -Release: 24%{?dist} +Release: 25%{?dist} Summary: The GNOME Display Manager License: GPLv2+ @@ -61,6 +61,22 @@ Patch130001: 0001-manager-Don-t-leak-session-objects.patch Patch130002: 0002-session-Don-t-leak-remote-greeter-interface.patch Patch130003: 0003-xdmcp-display-factory-Clear-launch-environment-when-.patch +Patch140001: 0001-libgdm-drop-support-for-serializing-multiple-opens.patch +Patch140002: 0002-libgdm-don-t-keep-manager-proxy-around-longer-than-w.patch +Patch140003: 0003-libgdm-get-connection-explicitly.patch +Patch140004: 0004-libgdm-Drop-weak-refs-on-the-GDBusConnection.patch +Patch140005: 0005-libgdm-Unref-the-manager-propagated-from-task.patch +Patch140006: 0006-libgdm-Don-t-double-ref-the-connection-got-from-task.patch +Patch140007: 0007-libgdm-Don-t-leak-connection-on-sync-re-authenticati.patch +Patch140008: 0008-libgdm-Use-auto-pointers-and-cleanup-code.patch +Patch140009: 0009-libgdb-Try-to-reuse-connections-from-the-available-p.patch +Patch140010: 0010-libgdm-Don-t-save-manager-address.patch +Patch140011: 0011-libgdm-Return-NULL-on-invalid-client-instances.patch +Patch140012: 0012-libgdm-use-g_autoptr-to-manage-objects-lifecycle.patch +Patch140013: 0013-libgdm-Fix-client-leaks-from-g_async_result_get_sour.patch +Patch140014: 0014-libgdm-Fetch-connection-synchronously.patch +Patch140015: 0015-libgdm-Don-t-leak-user-verifier-extensions-on-unlock.patch + Patch900000: audit-4.patch Patch900001: clear-screen.patch Patch900002: 0001-gdm.conf-custom.in-strip-out-reference-to-wayland.patch @@ -388,6 +404,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || : %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Fri Sep 25 2020 Ray Strode - 3.28.2-25 +- Backport some libgdm leak fixes from upstream + Resolves: #1882821 + * Thu Sep 17 2020 Ray Strode 3.28.2-24 - Fix FD leak on logout Resolves: #1877583