From 83c0105b2972ff68b50a24101755b5e72a11872b Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 20 Oct 2015 16:48:17 -0400 Subject: [PATCH 1/3] gdm-session: emit verification-complete even for logins Right now we only emit verification-complete when the a user successfully reauthenticates. We should also do it when they successfully initially authenticate. This commit fixes that. https://bugzilla.gnome.org/show_bug.cgi?id=754814 --- daemon/gdm-session.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index 6faa7cd..0fedb7b 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -280,73 +280,72 @@ on_authorize_cb (GdmDBusWorker *proxy, if (worked) { gdm_session_accredit (self, service_name); } else { report_and_stop_conversation (self, service_name, error); } } static void on_establish_credentials_cb (GdmDBusWorker *proxy, GAsyncResult *res, gpointer user_data) { GdmSessionConversation *conversation = user_data; GdmSession *self; char *service_name; GError *error = NULL; gboolean worked; worked = gdm_dbus_worker_call_establish_credentials_finish (proxy, res, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = conversation->session; service_name = conversation->service_name; if (worked) { - switch (self->priv->verification_mode) { - case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE: - if (self->priv->user_verifier_interface != NULL) { - gdm_dbus_user_verifier_emit_verification_complete (self->priv->user_verifier_interface, - service_name); - g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); - } - break; + if (self->priv->user_verifier_interface != NULL) { + gdm_dbus_user_verifier_emit_verification_complete (self->priv->user_verifier_interface, + service_name); + g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); + } + switch (self->priv->verification_mode) { case GDM_SESSION_VERIFICATION_MODE_LOGIN: case GDM_SESSION_VERIFICATION_MODE_CHOOSER: gdm_session_open_session (self, service_name); break; + case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE: default: break; } } else { report_and_stop_conversation (self, service_name, error); } } static const char ** get_system_session_dirs (void) { static const char *search_dirs[] = { "/etc/X11/sessions/", DMCONFDIR "/Sessions/", DATADIR "/gdm/BuiltInSessions/", DATADIR "/xsessions/", #ifdef ENABLE_WAYLAND_SUPPORT DATADIR "/wayland-sessions/", #endif NULL }; return search_dirs; } static gboolean is_prog_in_path (const char *prog) { char *f; gboolean ret; -- 2.7.0 From 34a302282a323820f83e76978cd0a07b2ee0304b Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 22 Jan 2016 15:59:00 -0500 Subject: [PATCH 2/3] session: keep session object alive while establishing credentials The only reference to session objects gets cleaned up when verification-complete is emitted, which happens in the middle of the establish_credentials handler. This commit makes sure the session object stays alive until the handler completes to prevent a crash. https://bugzilla.gnome.org/show_bug.cgi?id=754814 --- daemon/gdm-session.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index 0fedb7b..dbd4ba6 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -276,82 +276,85 @@ on_authorize_cb (GdmDBusWorker *proxy, return; self = conversation->session; service_name = conversation->service_name; if (worked) { gdm_session_accredit (self, service_name); } else { report_and_stop_conversation (self, service_name, error); } } static void on_establish_credentials_cb (GdmDBusWorker *proxy, GAsyncResult *res, gpointer user_data) { GdmSessionConversation *conversation = user_data; GdmSession *self; char *service_name; GError *error = NULL; gboolean worked; worked = gdm_dbus_worker_call_establish_credentials_finish (proxy, res, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; - self = conversation->session; - service_name = conversation->service_name; + self = g_object_ref (conversation->session); + service_name = g_strdup (conversation->service_name); if (worked) { if (self->priv->user_verifier_interface != NULL) { gdm_dbus_user_verifier_emit_verification_complete (self->priv->user_verifier_interface, service_name); g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); } switch (self->priv->verification_mode) { case GDM_SESSION_VERIFICATION_MODE_LOGIN: case GDM_SESSION_VERIFICATION_MODE_CHOOSER: gdm_session_open_session (self, service_name); break; case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE: default: break; } } else { report_and_stop_conversation (self, service_name, error); } + + g_free (service_name); + g_object_unref (self); } static const char ** get_system_session_dirs (void) { static const char *search_dirs[] = { "/etc/X11/sessions/", DMCONFDIR "/Sessions/", DATADIR "/gdm/BuiltInSessions/", DATADIR "/xsessions/", #ifdef ENABLE_WAYLAND_SUPPORT DATADIR "/wayland-sessions/", #endif NULL }; return search_dirs; } static gboolean is_prog_in_path (const char *prog) { char *f; gboolean ret; f = g_find_program_in_path (prog); ret = (f != NULL); g_free (f); return ret; } -- 2.7.0 From 48e264a2e3fbb5854125fc03a9ea3822abb68b94 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 22 Jan 2016 16:01:20 -0500 Subject: [PATCH 3/3] session: free conversation hash when disposing session We're currently leaking the hash table when disposing the session, this commit fixes that. https://bugzilla.gnome.org/show_bug.cgi?id=754814 --- daemon/gdm-session.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index dbd4ba6..09e6a48 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -3296,60 +3296,63 @@ gdm_session_get_property (GObject *object, break; case PROP_DISPLAY_IS_INITIAL: g_value_set_boolean (value, self->priv->display_is_initial); break; case PROP_VERIFICATION_MODE: g_value_set_enum (value, self->priv->verification_mode); break; case PROP_ALLOWED_USER: g_value_set_uint (value, self->priv->allowed_user); break; case PROP_CONVERSATION_ENVIRONMENT: g_value_set_pointer (value, self->priv->environment); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gdm_session_dispose (GObject *object) { GdmSession *self; self = GDM_SESSION (object); g_debug ("GdmSession: Disposing session"); gdm_session_close (self); + g_clear_pointer (&self->priv->conversations, + g_hash_table_unref); + g_clear_object (&self->priv->user_verifier_interface); g_clear_object (&self->priv->greeter_interface); g_clear_object (&self->priv->chooser_interface); g_free (self->priv->display_name); self->priv->display_name = NULL; g_free (self->priv->display_hostname); self->priv->display_hostname = NULL; g_free (self->priv->display_device); self->priv->display_device = NULL; g_free (self->priv->display_seat_id); self->priv->display_seat_id = NULL; g_free (self->priv->display_x11_authority_file); self->priv->display_x11_authority_file = NULL; g_strfreev (self->priv->conversation_environment); self->priv->conversation_environment = NULL; if (self->priv->worker_server != NULL) { g_dbus_server_stop (self->priv->worker_server); g_clear_object (&self->priv->worker_server); } if (self->priv->outside_server != NULL) { g_dbus_server_stop (self->priv->outside_server); g_clear_object (&self->priv->outside_server); -- 2.7.0