From 2615fb4ffe05b2640c15f4a9706796fe3b1376a9 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 25 Sep 2020 15:27:47 -0400 Subject: 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 93817127..5ac73944 100644 --- a/libgdm/gdm-client.c +++ b/libgdm/gdm-client.c @@ -172,11 +172,13 @@ static void maybe_complete_user_verifier_proxy_operation (GdmClient *client, UserVerifierData *data) { + GHashTable *user_verifier_extensions; GHashTableIter iter; gpointer key, value; - if (client->user_verifier_extensions != NULL) { - g_hash_table_iter_init (&iter, client->user_verifier_extensions); + user_verifier_extensions = g_object_get_data (G_OBJECT (client->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; @@ -191,19 +193,21 @@ 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->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->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); @@ -215,6 +219,7 @@ on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, UserVerifierData *data) { g_autoptr(GdmClient) client = NULL; + GHashTable *user_verifier_extensions; GCancellable *cancellable; GDBusConnection *connection; g_autoptr(GError) error = NULL; @@ -222,6 +227,7 @@ on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, 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); @@ -236,11 +242,11 @@ on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, for (i = 0; client->enabled_extensions[i] != NULL; i++) { g_debug ("Enabled extensions[%lu] = %s", i, client->enabled_extensions[i]); - g_hash_table_insert (client->user_verifier_extensions, client->enabled_extensions[i], NULL); + g_hash_table_insert (user_verifier_extensions, client->enabled_extensions[i], NULL); if (strcmp (client->enabled_extensions[i], gdm_user_verifier_choice_list_interface_info ()->name) == 0) { - g_hash_table_insert (client->user_verifier_extensions, client->enabled_extensions[i], NULL); + g_hash_table_insert (user_verifier_extensions, client->enabled_extensions[i], NULL); gdm_user_verifier_choice_list_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE, NULL, @@ -251,12 +257,12 @@ on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, data); } else { g_debug ("User verifier extension %s is unsupported", client->enabled_extensions[i]); - g_hash_table_remove (client->user_verifier_extensions, + g_hash_table_remove (user_verifier_extensions, client->enabled_extensions[i]); } } - if (g_hash_table_size (client->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); } @@ -278,6 +284,7 @@ on_user_verifier_proxy_created (GObject *source, 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; @@ -300,11 +307,15 @@ on_user_verifier_proxy_created (GObject *source, return; } - self->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 *) @@ -662,13 +673,19 @@ gdm_client_get_user_verifier_sync (GdmClient *client, (gpointer *) &client->user_verifier); if (client->enabled_extensions != NULL) { + GHashTable *user_verifier_extensions; gboolean res; - client->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->user_verifier), + "gdm-client-user-verifier-extensions", + user_verifier_extensions, + (GDestroyNotify) g_hash_table_unref); + res = gdm_user_verifier_call_enable_extensions_sync (client->user_verifier, (const char * const *) client->enabled_extensions, @@ -688,7 +705,7 @@ gdm_client_get_user_verifier_sync (GdmClient *client, cancellable, NULL); if (choice_list_interface != NULL) - g_hash_table_insert (client->user_verifier_extensions, client->enabled_extensions[i], choice_list_interface); + g_hash_table_insert (user_verifier_extensions, client->enabled_extensions[i], choice_list_interface); } } } @@ -790,12 +807,18 @@ gdm_client_get_user_verifier_finish (GdmClient *client, if (user_verifier == NULL) return NULL; - client->user_verifier = user_verifier; + if (client->user_verifier != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->user_verifier), + (gpointer *) + &client->user_verifier); + } g_object_add_weak_pointer (G_OBJECT (client->user_verifier), (gpointer *) &client->user_verifier); + client->user_verifier = user_verifier; + return user_verifier; } @@ -812,10 +835,13 @@ gdm_client_get_user_verifier_finish (GdmClient *client, GdmUserVerifierChoiceList * gdm_client_get_user_verifier_choice_list (GdmClient *client) { - if (client->user_verifier_extensions == NULL) + GHashTable *user_verifier_extensions; + + user_verifier_extensions = g_object_get_data (G_OBJECT (client->user_verifier), "gdm-client-user-verifier-extensions"); + if (user_verifier_extensions == NULL) return NULL; - return g_hash_table_lookup (client->user_verifier_extensions, + return g_hash_table_lookup (user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name); } -- cgit v1.2.1