diff options
author | Ray Strode <rstrode@redhat.com> | 2020-09-25 15:27:47 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2021-04-12 16:57:53 -0400 |
commit | 204ac2f82cec9c6c5cdfd6dffcf09d7f9e047a46 (patch) | |
tree | 9f020114bfb88b38ca56550bab85c6b7b0f58b52 | |
parent | d399c1b843e53b3bdf0cdd323a3643838893af5e (diff) | |
download | gdm-204ac2f82cec9c6c5cdfd6dffcf09d7f9e047a46.tar.gz |
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.
-rw-r--r-- | libgdm/gdm-client.c | 165 |
1 files changed, 131 insertions, 34 deletions
diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c index afe78087..7074cb14 100644 --- a/libgdm/gdm-client.c +++ b/libgdm/gdm-client.c @@ -41,6 +41,7 @@ struct GdmClientPrivate { GdmUserVerifier *user_verifier; + GdmUserVerifier *user_verifier_for_reauth; GHashTable *user_verifier_extensions; GdmGreeter *greeter; @@ -174,11 +175,13 @@ 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 (data->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; @@ -193,19 +196,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->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); @@ -217,6 +222,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; @@ -224,6 +230,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); @@ -238,11 +245,11 @@ on_user_verifier_extensions_enabled (GdmUserVerifier *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, @@ -253,12 +260,12 @@ on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, 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); } @@ -280,6 +287,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; @@ -302,11 +310,15 @@ on_user_verifier_proxy_created (GObject *source, 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 *) @@ -560,6 +572,20 @@ gdm_client_open_reauthentication_channel_sync (GdmClient *client, cancellable, error); + if (client->priv->user_verifier_for_reauth != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier_for_reauth), + (gpointer *) + &client->priv->user_verifier_for_reauth); + } + + client->priv->user_verifier_for_reauth = user_verifier; + + if (user_verifier != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier_for_reauth), + (gpointer *) + &client->priv->user_verifier_for_reauth); + } + return user_verifier; } @@ -619,9 +645,27 @@ gdm_client_open_reauthentication_channel_finish (GdmClient *client, GAsyncResult *result, GError **error) { + GdmUserVerifier *user_verifier; + g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); - return g_task_propagate_pointer (G_TASK (result), error); + user_verifier = g_task_propagate_pointer (G_TASK (result), error); + + if (client->priv->user_verifier_for_reauth != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier_for_reauth), + (gpointer *) + &client->priv->user_verifier_for_reauth); + } + + client->priv->user_verifier_for_reauth = user_verifier; + + if (user_verifier != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier_for_reauth), + (gpointer *) + &client->priv->user_verifier_for_reauth); + } + + return user_verifier; } /** @@ -664,13 +708,19 @@ gdm_client_get_user_verifier_sync (GdmClient *client, (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, @@ -690,7 +740,7 @@ gdm_client_get_user_verifier_sync (GdmClient *client, 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); } } } @@ -792,11 +842,19 @@ gdm_client_get_user_verifier_finish (GdmClient *client, if (user_verifier == NULL) return NULL; + if (client->priv->user_verifier != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + } + client->priv->user_verifier = user_verifier; - g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), - (gpointer *) - &client->priv->user_verifier); + if (user_verifier != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier), + (gpointer *) + &client->priv->user_verifier); + } return user_verifier; } @@ -814,10 +872,18 @@ gdm_client_get_user_verifier_finish (GdmClient *client, GdmUserVerifierChoiceList * gdm_client_get_user_verifier_choice_list (GdmClient *client) { - if (client->priv->user_verifier_extensions == NULL) + GHashTable *user_verifier_extensions = NULL; + + if (client->priv->user_verifier_for_reauth != NULL) + user_verifier_extensions = g_object_get_data (G_OBJECT (client->priv->user_verifier_for_reauth), "gdm-client-user-verifier-extensions"); + + if (user_verifier_extensions == NULL && client->priv->user_verifier != NULL) + 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); } @@ -956,11 +1022,19 @@ gdm_client_get_greeter_finish (GdmClient *client, if (greeter == NULL) return NULL; + if (client->priv->greeter != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + } + client->priv->greeter = greeter; - g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), - (gpointer *) - &client->priv->greeter); + if (greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->greeter), + (gpointer *) + &client->priv->greeter); + } return greeter; } @@ -1126,11 +1200,19 @@ gdm_client_get_remote_greeter_finish (GdmClient *client, if (remote_greeter == NULL) return NULL; + if (client->priv->remote_greeter != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + } + client->priv->remote_greeter = remote_greeter; - g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), - (gpointer *) - &client->priv->remote_greeter); + if (remote_greeter != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->remote_greeter), + (gpointer *) + &client->priv->remote_greeter); + } return remote_greeter; } @@ -1294,11 +1376,19 @@ gdm_client_get_chooser_finish (GdmClient *client, if (chooser == NULL) return NULL; + if (client->priv->chooser != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + } + client->priv->chooser = chooser; - g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), - (gpointer *) - &client->priv->chooser); + if (chooser != NULL) { + g_object_add_weak_pointer (G_OBJECT (client->priv->chooser), + (gpointer *) + &client->priv->chooser); + } return chooser; } @@ -1382,6 +1472,13 @@ gdm_client_finalize (GObject *object) g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier), (gpointer *) &client->priv->user_verifier); + + } + + if (client->priv->user_verifier_for_reauth != NULL) { + g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier_for_reauth), + (gpointer *) + &client->priv->user_verifier_for_reauth); } if (client->priv->greeter != NULL) { |