Blame SOURCES/0007-daemon-run-PostSession-script-from-mnager-not-worker.patch

c4edd0
From ab06d95076705cdaee9945adb2e22ac75be72952 Mon Sep 17 00:00:00 2001
c4edd0
From: Ray Strode <rstrode@redhat.com>
c4edd0
Date: Thu, 29 Aug 2019 09:34:04 -0400
c4edd0
Subject: [PATCH 7/7] daemon: run PostSession script from mnager not worker
c4edd0
c4edd0
After a user logs out, the session worker baby sitting
c4edd0
the session, may optionally run admin provided PostSession
c4edd0
scripts.
c4edd0
c4edd0
Those scripts aren't getting reliably run on reboots, because
c4edd0
systemd kills the worker prematurely.
c4edd0
c4edd0
There's no easy way to prevent this... the worker is part of
c4edd0
the user session and user sessions are terminated immediately
c4edd0
at shutdown time.
c4edd0
c4edd0
This commit moves PostSession handling to the daemon process,
c4edd0
where it can happen unimpeded by session bring down.
c4edd0
c4edd0
This also makes the scripts more reliable in other potential
c4edd0
cases where the worker is killed explicitly.
c4edd0
---
c4edd0
 daemon/gdm-manager.c        | 40 +++++++++++++++++++++++++++++++++++++
c4edd0
 daemon/gdm-session-worker.c |  3 ---
c4edd0
 2 files changed, 40 insertions(+), 3 deletions(-)
c4edd0
c4edd0
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
c4edd0
index 779b716be..d31c9d718 100644
c4edd0
--- a/daemon/gdm-manager.c
c4edd0
+++ b/daemon/gdm-manager.c
c4edd0
@@ -1933,70 +1933,107 @@ on_user_session_opened (GdmSession       *session,
c4edd0
                                                       g_object_ref (session));
c4edd0
         if (g_strcmp0 (service_name, "gdm-autologin") == 0 &&
c4edd0
             !gdm_session_client_is_connected (session)) {
c4edd0
                 /* If we're auto logging in then don't wait for the go-ahead from a greeter,
c4edd0
                  * (since there is no greeter) */
c4edd0
                 g_object_set_data (G_OBJECT (session), "start-when-ready", GINT_TO_POINTER (TRUE));
c4edd0
         }
c4edd0
 
c4edd0
         start_user_session_if_ready (manager, session, service_name);
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 on_user_session_started (GdmSession      *session,
c4edd0
                          const char      *service_name,
c4edd0
                          GPid             pid,
c4edd0
                          GdmManager      *manager)
c4edd0
 {
c4edd0
         g_debug ("GdmManager: session started %d", pid);
c4edd0
         add_session_record (manager, session, pid, SESSION_RECORD_LOGIN);
c4edd0
 
c4edd0
 #ifdef WITH_PLYMOUTH
c4edd0
         if (g_strcmp0 (service_name, "gdm-autologin") == 0) {
c4edd0
                 if (manager->priv->plymouth_is_running) {
c4edd0
                         g_timeout_add_seconds (20, (GSourceFunc) plymouth_quit_with_transition, NULL);
c4edd0
                         manager->priv->plymouth_is_running = FALSE;
c4edd0
                 }
c4edd0
         }
c4edd0
 #endif
c4edd0
 }
c4edd0
 
c4edd0
+static void
c4edd0
+run_post_session_script (GdmSession *session)
c4edd0
+{
c4edd0
+        GPid pid;
c4edd0
+        GdmDisplay *display;
c4edd0
+        gboolean display_is_local = FALSE;
c4edd0
+        const char *username;
c4edd0
+        g_autofree char *display_name = NULL, *remote_hostname = NULL, *display_auth_file = NULL;
c4edd0
+
c4edd0
+        display = get_display_for_user_session (session);
c4edd0
+
c4edd0
+        if (display == NULL)
c4edd0
+                return;
c4edd0
+
c4edd0
+        pid = gdm_session_get_pid (session);
c4edd0
+
c4edd0
+        if (pid <= 0)
c4edd0
+                return;
c4edd0
+
c4edd0
+        username = gdm_session_get_username (session);
c4edd0
+
c4edd0
+        g_object_get (G_OBJECT (display),
c4edd0
+                      "x11-display-name", &display_name,
c4edd0
+                      "is-local", &display_is_local,
c4edd0
+                      "remote-hostname", &remote_hostname,
c4edd0
+                      "x11-authority-file", &display_auth_file,
c4edd0
+                      NULL);
c4edd0
+
c4edd0
+        gdm_run_script (GDMCONFDIR "/PostSession",
c4edd0
+                        username,
c4edd0
+                        display_name,
c4edd0
+                        display_is_local? NULL : remote_hostname,
c4edd0
+                        display_auth_file);
c4edd0
+}
c4edd0
+
c4edd0
 static void
c4edd0
 remove_user_session (GdmManager *manager,
c4edd0
                      GdmSession *session)
c4edd0
 {
c4edd0
         GList *node;
c4edd0
         GdmDisplay *display;
c4edd0
 
c4edd0
         display = get_display_for_user_session (session);
c4edd0
 
c4edd0
         if (display != NULL) {
c4edd0
+                run_post_session_script (session);
c4edd0
+
c4edd0
                 gdm_display_unmanage (display);
c4edd0
                 gdm_display_finish (display);
c4edd0
         }
c4edd0
 
c4edd0
         node = g_list_find (manager->priv->user_sessions, session);
c4edd0
 
c4edd0
         if (node != NULL) {
c4edd0
                 manager->priv->user_sessions = g_list_delete_link (manager->priv->user_sessions, node);
c4edd0
                 gdm_session_close (session);
c4edd0
                 g_object_unref (session);
c4edd0
         }
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 on_session_start_failed (GdmSession *session,
c4edd0
                          const char *service_name,
c4edd0
                          const char *message,
c4edd0
                          GdmManager *manager)
c4edd0
 {
c4edd0
         g_debug ("GdmManager: session failed to start: %s", message);
c4edd0
         remove_user_session (manager, session);
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 on_user_session_exited (GdmSession *session,
c4edd0
                         int         code,
c4edd0
                         GdmManager *manager)
c4edd0
 {
c4edd0
         GPid pid;
c4edd0
 
c4edd0
@@ -2753,60 +2790,63 @@ finish_display (const char *id,
c4edd0
         if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED)
c4edd0
                 gdm_display_unmanage (display);
c4edd0
         gdm_display_finish (display);
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 gdm_manager_dispose (GObject *object)
c4edd0
 {
c4edd0
         GdmManager *manager;
c4edd0
 
c4edd0
         g_return_if_fail (object != NULL);
c4edd0
         g_return_if_fail (GDM_IS_MANAGER (object));
c4edd0
 
c4edd0
         manager = GDM_MANAGER (object);
c4edd0
 
c4edd0
         g_return_if_fail (manager->priv != NULL);
c4edd0
 
c4edd0
         gdm_manager_stop (manager);
c4edd0
 
c4edd0
 #ifdef HAVE_LIBXDMCP
c4edd0
         g_clear_object (&manager->priv->xdmcp_factory);
c4edd0
 #endif
c4edd0
         g_clear_object (&manager->priv->local_factory);
c4edd0
         g_clear_pointer (&manager->priv->open_reauthentication_requests,
c4edd0
                          (GDestroyNotify)
c4edd0
                          g_hash_table_unref);
c4edd0
         g_clear_pointer (&manager->priv->transient_sessions,
c4edd0
                          (GDestroyNotify)
c4edd0
                          g_hash_table_unref);
c4edd0
 
c4edd0
+        g_list_foreach (manager->priv->user_sessions,
c4edd0
+                        (GFunc) run_post_session_script,
c4edd0
+                        NULL);
c4edd0
         g_list_foreach (manager->priv->user_sessions,
c4edd0
                         (GFunc) gdm_session_close,
c4edd0
                         NULL);
c4edd0
         g_list_free_full (manager->priv->user_sessions, (GDestroyNotify) g_object_unref);
c4edd0
         manager->priv->user_sessions = NULL;
c4edd0
 
c4edd0
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
c4edd0
                                               G_CALLBACK (on_display_added),
c4edd0
                                               manager);
c4edd0
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
c4edd0
                                               G_CALLBACK (on_display_removed),
c4edd0
                                               manager);
c4edd0
 
c4edd0
         if (!g_dbus_connection_is_closed (manager->priv->connection)) {
c4edd0
                 gdm_display_store_foreach (manager->priv->display_store,
c4edd0
                                            (GdmDisplayStoreFunc)unexport_display,
c4edd0
                                            manager);
c4edd0
                 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (manager));
c4edd0
         }
c4edd0
 
c4edd0
         gdm_display_store_foreach (manager->priv->display_store,
c4edd0
                                    (GdmDisplayStoreFunc) finish_display,
c4edd0
                                    manager);
c4edd0
 
c4edd0
         gdm_display_store_clear (manager->priv->display_store);
c4edd0
 
c4edd0
         g_dbus_object_manager_server_set_connection (manager->priv->object_manager, NULL);
c4edd0
 
c4edd0
         g_clear_object (&manager->priv->connection);
c4edd0
         g_clear_object (&manager->priv->object_manager);
c4edd0
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
c4edd0
index 07117d857..b0861b971 100644
c4edd0
--- a/daemon/gdm-session-worker.c
c4edd0
+++ b/daemon/gdm-session-worker.c
c4edd0
@@ -1743,72 +1743,69 @@ gdm_session_worker_get_environment (GdmSessionWorker *worker)
c4edd0
 static gboolean
c4edd0
 run_script (GdmSessionWorker *worker,
c4edd0
             const char       *dir)
c4edd0
 {
c4edd0
         /* scripts are for non-program sessions only */
c4edd0
         if (worker->priv->is_program_session) {
c4edd0
                 return TRUE;
c4edd0
         }
c4edd0
 
c4edd0
         return gdm_run_script (dir,
c4edd0
                                worker->priv->username,
c4edd0
                                worker->priv->x11_display_name,
c4edd0
                                worker->priv->display_is_local? NULL : worker->priv->hostname,
c4edd0
                                worker->priv->x11_authority_file);
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 session_worker_child_watch (GPid              pid,
c4edd0
                             int               status,
c4edd0
                             GdmSessionWorker *worker)
c4edd0
 {
c4edd0
         g_debug ("GdmSessionWorker: child (pid:%d) done (%s:%d)",
c4edd0
                  (int) pid,
c4edd0
                  WIFEXITED (status) ? "status"
c4edd0
                  : WIFSIGNALED (status) ? "signal"
c4edd0
                  : "unknown",
c4edd0
                  WIFEXITED (status) ? WEXITSTATUS (status)
c4edd0
                  : WIFSIGNALED (status) ? WTERMSIG (status)
c4edd0
                  : -1);
c4edd0
 
c4edd0
-
c4edd0
         gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
c4edd0
 
c4edd0
         gdm_dbus_worker_emit_session_exited (GDM_DBUS_WORKER (worker),
c4edd0
                                              worker->priv->service,
c4edd0
                                              status);
c4edd0
-
c4edd0
         killpg (pid, SIGHUP);
c4edd0
 
c4edd0
         worker->priv->child_pid = -1;
c4edd0
         worker->priv->child_watch_id = 0;
c4edd0
-        run_script (worker, GDMCONFDIR "/PostSession");
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 gdm_session_worker_watch_child (GdmSessionWorker *worker)
c4edd0
 {
c4edd0
         g_debug ("GdmSession worker: watching pid %d", worker->priv->child_pid);
c4edd0
         worker->priv->child_watch_id = g_child_watch_add (worker->priv->child_pid,
c4edd0
                                                           (GChildWatchFunc)session_worker_child_watch,
c4edd0
                                                           worker);
c4edd0
 
c4edd0
 }
c4edd0
 
c4edd0
 static gboolean
c4edd0
 _is_loggable_file (const char* filename)
c4edd0
 {
c4edd0
         struct stat file_info;
c4edd0
 
c4edd0
         if (g_lstat (filename, &file_info) < 0) {
c4edd0
                 return FALSE;
c4edd0
         }
c4edd0
 
c4edd0
         return S_ISREG (file_info.st_mode) && g_access (filename, R_OK | W_OK) == 0;
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 rotate_logs (const char *path,
c4edd0
              guint       n_copies)
c4edd0
 {
c4edd0
         int i;
c4edd0
 
c4edd0
-- 
c4edd0
2.21.0
c4edd0