Blob Blame History Raw
From c3f39b437f6ef32174f322bd107071cdf1379d12 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 18 Apr 2016 16:09:08 -0400
Subject: [PATCH 1/2] worker: run PostLogin/PreSession scripts later

Right now we run them while the login screen is still up, so
they have no way of showing UI to the user.

This commit moves them until after the login screen is torn
down.
---
 daemon/gdm-session-worker.c | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index acc826b..e07d32e 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -1793,60 +1793,78 @@ out:
 }
 
 static gboolean
 gdm_session_worker_start_session (GdmSessionWorker  *worker,
                                   GError           **error)
 {
         struct passwd *passwd_entry;
         pid_t session_pid;
         int   error_code;
 
         gdm_get_pwent_for_name (worker->priv->username, &passwd_entry);
         if (worker->priv->is_program_session) {
                 g_debug ("GdmSessionWorker: opening session for program '%s'",
                          worker->priv->arguments[0]);
         } else {
                 g_debug ("GdmSessionWorker: opening user session with program '%s'",
                          worker->priv->arguments[0]);
         }
 
         error_code = PAM_SUCCESS;
 
 #ifdef ENABLE_WAYLAND_SUPPORT
         /* If we're in new vt mode, jump to the new vt now. There's no need to jump for
          * the other two modes: in the logind case, the session will activate itself when
          * ready, and in the reuse server case, we're already on the correct VT. */
         if (worker->priv->display_mode == GDM_SESSION_DISPLAY_MODE_NEW_VT) {
                 jump_to_vt (worker, worker->priv->session_vt);
         }
 #endif
 
+        if (!worker->priv->is_program_session && !run_script (worker, GDMCONFDIR "/PostLogin")) {
+                g_set_error (error,
+                             GDM_SESSION_WORKER_ERROR,
+                             GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
+                             "Failed to execute PostLogin script");
+                error_code = PAM_ABORT;
+                goto out;
+        }
+
+        if (!worker->priv->is_program_session && !run_script (worker, GDMCONFDIR "/PreSession")) {
+                g_set_error (error,
+                             GDM_SESSION_WORKER_ERROR,
+                             GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
+                             "Failed to execute PreSession script");
+                error_code = PAM_ABORT;
+                goto out;
+        }
+
         session_pid = fork ();
 
         if (session_pid < 0) {
                 g_set_error (error,
                              GDM_SESSION_WORKER_ERROR,
                              GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
                              "%s", g_strerror (errno));
                 error_code = PAM_ABORT;
                 goto out;
         }
 
         if (session_pid == 0) {
                 const char * const * environment;
                 char  *home_dir;
                 int    stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
                 gboolean has_journald = FALSE;
                 sigset_t mask;
 
                 /* Leak the TTY into the session as stdin so that it stays open
                  * without any races. */
                 if (worker->priv->session_tty_fd > 0) {
                         dup2 (worker->priv->session_tty_fd, STDIN_FILENO);
                         close (worker->priv->session_tty_fd);
                         worker->priv->session_tty_fd = -1;
                 } else {
                         stdin_fd = open ("/dev/null", O_RDWR);
                         dup2 (stdin_fd, STDIN_FILENO);
                         close (stdin_fd);
                 }
 
@@ -2186,93 +2204,77 @@ gdm_session_worker_open_session (GdmSessionWorker  *worker,
 
         g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
         g_assert (geteuid () == 0);
 
         switch (worker->priv->display_mode) {
         case GDM_SESSION_DISPLAY_MODE_REUSE_VT:
                 if (!set_up_for_current_vt (worker, error)) {
                         return FALSE;
                 }
                 break;
 #ifdef ENABLE_WAYLAND_SUPPORT
         case GDM_SESSION_DISPLAY_MODE_NEW_VT:
         case GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED:
                 if (!set_up_for_new_vt (worker)) {
                         g_set_error (error,
                                      GDM_SESSION_WORKER_ERROR,
                                      GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
                                      "Unable to open VT");
                         return FALSE;
                 }
                 break;
 #endif
         }
 
         flags = 0;
 
         if (worker->priv->is_program_session) {
                 flags |= PAM_SILENT;
         }
 
-        if (!run_script (worker, GDMCONFDIR "/PostLogin")) {
-                g_set_error (error,
-                             GDM_SESSION_WORKER_ERROR,
-                             GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
-                             "Failed to execute PostLogin script");
-                return FALSE;
-        }
-
         error_code = pam_open_session (worker->priv->pam_handle, flags);
 
         if (error_code != PAM_SUCCESS) {
                 g_set_error (error,
                              GDM_SESSION_WORKER_ERROR,
                              GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
                              "%s", pam_strerror (worker->priv->pam_handle, error_code));
                 goto out;
         }
 
         g_debug ("GdmSessionWorker: state SESSION_OPENED");
         worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_OPENED;
 
 #ifdef WITH_SYSTEMD
         session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID");
 #endif
 
-        /* FIXME: should we do something here?
-         * Note that error return status from PreSession script should
-         * be ignored in the case of a X-GDM-BypassXsession session, which can
-         * be checked by calling:
-         * gdm_session_bypasses_xsession (session)
-         */
-        run_script (worker, GDMCONFDIR "/PreSession");
-
 #ifdef WITH_CONSOLE_KIT
         register_ck_session (worker);
 
         if (session_id == NULL) {
                 session_id = get_ck_session_id (worker);
         }
 #endif
 
         if (session_id != NULL) {
                 g_free (worker->priv->session_id);
                 worker->priv->session_id = session_id;
         }
 
  out:
         if (error_code != PAM_SUCCESS) {
                 gdm_session_worker_uninitialize_pam (worker, error_code);
                 return FALSE;
         }
 
         gdm_session_worker_get_username (worker, NULL);
         gdm_session_auditor_report_login (worker->priv->auditor);
 
         return TRUE;
 }
 
 static void
 gdm_session_worker_set_server_address (GdmSessionWorker *worker,
                                        const char       *address)
 {
         g_free (worker->priv->server_address);
-- 
2.8.1


From ebc5a37f8f4a287df4255cbcdf5d51f7a8fe9b44 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 19 Apr 2016 11:02:08 -0400
Subject: [PATCH 2/2] manager: handle session failing to start

Right now if a session fails really early in the start up
process, we fail to handle it.

This commit fixes that.
---
 daemon/gdm-manager.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 33064ea..72ea968 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1475,60 +1475,69 @@ on_session_started (GdmSession      *session,
 
                 session_id = gdm_session_get_session_id (session);
                 g_object_set (GDM_SLAVE (slave), "session-id", session_id, NULL);
         }
 }
 
 static void
 remove_user_session (GdmManager *manager,
                      GdmSession *session)
 {
         GList *node;
         GdmDisplay *display;
 
         display = get_display_for_user_session (session);
 
         if (display != NULL) {
                 gdm_display_unmanage (display);
                 gdm_display_finish (display);
         }
 
         node = g_list_find (manager->priv->user_sessions, session);
 
         if (node != NULL) {
                 manager->priv->user_sessions = g_list_delete_link (manager->priv->user_sessions, node);
                 gdm_session_close (session);
                 g_object_unref (session);
         }
 }
 
 static void
+on_session_start_failed (GdmSession *session,
+                         const char *service_name,
+                         GdmManager *manager)
+{
+        g_debug ("GdmManager: session failed to start");
+        remove_user_session (manager, session);
+}
+
+static void
 on_user_session_exited (GdmSession *session,
                         int         code,
                         GdmManager *manager)
 {
         g_debug ("GdmManager: session exited with status %d", code);
         remove_user_session (manager, session);
 }
 
 static void
 on_user_session_died (GdmSession *session,
                       int         signal_number,
                       GdmManager *manager)
 {
         g_debug ("GdmManager: session died with signal %s", strsignal (signal_number));
         remove_user_session (manager, session);
 }
 
 static char *
 query_ck_for_display_device (GdmManager *manager,
                              GdmDisplay *display)
 {
         char    *out;
         char    *command;
         char    *display_name = NULL;
         int      status;
         gboolean res;
         GError  *error;
 
         g_object_get (G_OBJECT (display),
                       "x11-display-name", &display_name,
@@ -1894,60 +1903,64 @@ create_seed_session_for_display (GdmManager *manager,
                           manager);
         g_signal_connect (session,
                           "client-connected",
                           G_CALLBACK (on_session_client_connected),
                           manager);
         g_signal_connect (session,
                           "client-disconnected",
                           G_CALLBACK (on_session_client_disconnected),
                           manager);
         g_signal_connect (session,
                           "cancelled",
                           G_CALLBACK (on_session_cancelled),
                           manager);
         g_signal_connect (session,
                           "conversation-started",
                           G_CALLBACK (on_session_conversation_started),
                           manager);
         g_signal_connect (session,
                           "conversation-stopped",
                           G_CALLBACK (on_session_conversation_stopped),
                           manager);
         g_signal_connect (session,
                           "session-opened",
                           G_CALLBACK (on_session_opened),
                           manager);
         g_signal_connect (session,
                           "session-started",
                           G_CALLBACK (on_session_started),
                           manager);
         g_signal_connect (session,
+                          "session-start-failed",
+                          G_CALLBACK (on_session_start_failed),
+                          manager);
+        g_signal_connect (session,
                           "session-exited",
                           G_CALLBACK (on_user_session_exited),
                           manager);
         g_signal_connect (session,
                           "session-died",
                           G_CALLBACK (on_user_session_died),
                           manager);
         g_object_set_data (G_OBJECT (session), "gdm-display", display);
         g_object_set_data_full (G_OBJECT (display), "gdm-seed-session", g_object_ref (session), (GDestroyNotify) g_object_unref);
 
         start_autologin_conversation_if_necessary (manager, display, session);
 }
 
 static void
 on_display_added (GdmDisplayStore *display_store,
                   const char      *id,
                   GdmManager      *manager)
 {
         GdmDisplay *display;
 
         display = gdm_display_store_lookup (display_store, id);
 
         if (display != NULL) {
                 g_dbus_object_manager_server_export (manager->priv->object_manager,
                                                      gdm_display_get_object_skeleton (display));
 
                 g_signal_connect (display, "notify::status",
                                   G_CALLBACK (on_display_status_changed),
                                   manager);
                 g_signal_emit (manager, signals[DISPLAY_ADDED], 0, id);
-- 
2.8.1