Blame SOURCES/0044-session-worker-ensure-initial-vt-is-never-picked-for.patch

e0b6b0
From 75b65846ca77bd2d42e25365b4b7242a406330cf Mon Sep 17 00:00:00 2001
c90517
From: Ray Strode <rstrode@redhat.com>
c90517
Date: Tue, 7 Apr 2020 14:37:41 -0400
e0b6b0
Subject: [PATCH 44/51] session-worker: ensure initial vt is never picked for
c90517
 !is_initial displays
c90517
c90517
Normally, a !is_initial display would never "get" tty1, since the system
c90517
boots to tty1.  But if, for some reason, the user booted to runlevel 3,
c90517
then switched to runlevel 5, the login screen could get started when
c90517
tty1 is free.
c90517
c90517
That means, e.g., an autologin user can end up getting allocated tty1,
c90517
which is bad, since we assume tty1 is used for the login screen.
c90517
c90517
This commit opens up /dev/tty1 when querying for available VTs, so that
c90517
it never gets returned by the kernel as available.
c90517
---
c90517
 daemon/gdm-session-worker.c | 39 +++++++++++++++++++++++++------------
c90517
 1 file changed, 27 insertions(+), 12 deletions(-)
c90517
c90517
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
c90517
index 0bd78cfaf..42c415837 100644
c90517
--- a/daemon/gdm-session-worker.c
c90517
+++ b/daemon/gdm-session-worker.c
c90517
@@ -2167,105 +2167,120 @@ gdm_session_worker_start_session (GdmSessionWorker  *worker,
c90517
 
c90517
         /* If we end up execing again, make sure we don't use the executable context set up
c90517
          * by pam_selinux durin pam_open_session
c90517
          */
c90517
 #ifdef HAVE_SELINUX
c90517
         setexeccon (NULL);
c90517
 #endif
c90517
 
c90517
         worker->priv->child_pid = session_pid;
c90517
 
c90517
         g_debug ("GdmSessionWorker: session opened creating reply...");
c90517
         g_assert (sizeof (GPid) <= sizeof (int));
c90517
 
c90517
         g_debug ("GdmSessionWorker: state SESSION_STARTED");
c90517
         gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_STARTED);
c90517
 
c90517
         gdm_session_worker_watch_child (worker);
c90517
 
c90517
  out:
c90517
         if (error_code != PAM_SUCCESS) {
c90517
                 gdm_session_worker_uninitialize_pam (worker, error_code);
c90517
                 return FALSE;
c90517
         }
c90517
 
c90517
         return TRUE;
c90517
 }
c90517
 
c90517
 static gboolean
c90517
 set_up_for_new_vt (GdmSessionWorker *worker)
c90517
 {
c90517
-        int fd;
c90517
+        int initial_vt_fd;
c90517
         char vt_string[256], tty_string[256];
c90517
         int session_vt = 0;
c90517
 
c90517
-        fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
c90517
-
c90517
-        if (fd < 0) {
c90517
-                g_debug ("GdmSessionWorker: couldn't open VT master: %m");
c90517
+        /* open the initial vt.  We need it for two scenarios:
c90517
+         *
c90517
+         * 1) display_is_initial is TRUE.  We need it directly.
c90517
+         * 2) display_is_initial is FALSE. We need it to mark
c90517
+         * the initial VT as "in use" so it doesn't get returned
c90517
+         * by VT_OPENQRY
c90517
+         * */
c90517
+        g_snprintf (tty_string, sizeof (tty_string), "/dev/tty%d", GDM_INITIAL_VT);
c90517
+        initial_vt_fd = open (tty_string, O_RDWR | O_NOCTTY);
c90517
+
c90517
+        if (initial_vt_fd < 0) {
c90517
+                g_debug ("GdmSessionWorker: couldn't open console of initial fd: %m");
c90517
                 return FALSE;
c90517
         }
c90517
 
c90517
         if (worker->priv->display_is_initial) {
c90517
                 session_vt = GDM_INITIAL_VT;
c90517
         } else {
c90517
-                if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
c90517
+
c90517
+                /* Typically VT_OPENQRY is called on /dev/tty0, but we already
c90517
+                 * have /dev/tty1 open above, so might as well use it.
c90517
+                 */
c90517
+                if (ioctl (initial_vt_fd, VT_OPENQRY, &session_vt) < 0) {
c90517
                         g_debug ("GdmSessionWorker: couldn't open new VT: %m");
c90517
                         goto fail;
c90517
                 }
c90517
         }
c90517
 
c90517
         worker->priv->session_vt = session_vt;
c90517
 
c90517
-        close (fd);
c90517
-        fd = -1;
c90517
-
c90517
         g_assert (session_vt > 0);
c90517
 
c90517
         g_snprintf (vt_string, sizeof (vt_string), "%d", session_vt);
c90517
 
c90517
         /* Set the VTNR. This is used by logind to configure a session in
c90517
          * the logind-managed case, but it doesn't hurt to set it always.
c90517
          * When logind gains support for XDG_VTNR=auto, we can make the
c90517
          * OPENQRY and this whole path only used by the new VT code. */
c90517
         gdm_session_worker_set_environment_variable (worker,
c90517
                                                      "XDG_VTNR",
c90517
                                                      vt_string);
c90517
 
c90517
-        g_snprintf (tty_string, 256, "/dev/tty%d", session_vt);
c90517
-        worker->priv->session_tty_fd = open (tty_string, O_RDWR | O_NOCTTY);
c90517
+        if (worker->priv->display_is_initial) {
c90517
+             worker->priv->session_tty_fd = initial_vt_fd;
c90517
+        } else {
c90517
+             g_snprintf (tty_string, sizeof (tty_string), "/dev/tty%d", session_vt);
c90517
+             worker->priv->session_tty_fd = open (tty_string, O_RDWR | O_NOCTTY);
c90517
+             close (initial_vt_fd);
c90517
+        }
c90517
+
c90517
         pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
c90517
 
c90517
         return TRUE;
c90517
 
c90517
 fail:
c90517
-        close (fd);
c90517
+        close (initial_vt_fd);
c90517
         return FALSE;
c90517
 }
c90517
 
c90517
 static gboolean
c90517
 set_xdg_vtnr_to_current_vt (GdmSessionWorker *worker)
c90517
 {
c90517
         int fd;
c90517
         char vt_string[256];
c90517
         struct vt_stat vt_state = { 0 };
c90517
 
c90517
         fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
c90517
 
c90517
         if (fd < 0) {
c90517
                 g_debug ("GdmSessionWorker: couldn't open VT master: %m");
c90517
                 return FALSE;
c90517
         }
c90517
 
c90517
         if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
c90517
                 g_debug ("GdmSessionWorker: couldn't get current VT: %m");
c90517
                 goto fail;
c90517
         }
c90517
 
c90517
         close (fd);
c90517
         fd = -1;
c90517
 
c90517
         g_snprintf (vt_string, sizeof (vt_string), "%d", vt_state.v_active);
c90517
 
c90517
         gdm_session_worker_set_environment_variable (worker,
c90517
                                                      "XDG_VTNR",
c90517
                                                      vt_string);
c90517
-- 
e0b6b0
2.27.0
c90517