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