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

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