Blob Blame History Raw
From 20725e4c65555178ed64a3cb77ee979ec98998f8 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 19 Oct 2022 14:50:33 -0400
Subject: [PATCH 2/2] manager: Fix btmp record accounting

Before a user logs in they don't have a display.

btmp records currently need a display though, and they
get written when the user can't log in.

Furthermore, the display from X11 point of view is
somewhat archaic. We use wayland by default now.

In lieu of a display, this commit gives the btmp record
the seat id instead.
---
 daemon/gdm-manager.c        | 11 +++++++++--
 daemon/gdm-session-record.c |  8 ++++++--
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 4b62b8b1..c70248f3 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -641,113 +641,120 @@ switch_to_compatible_user_session (GdmManager *manager,
 
         ret = TRUE;
 
  out:
         return ret;
 }
 
 static GdmDisplay *
 get_display_for_user_session (GdmSession *session)
 {
         return g_object_get_data (G_OBJECT (session), "gdm-display");
 }
 
 static GdmSession *
 get_user_session_for_display (GdmDisplay *display)
 {
         if (display == NULL) {
                 return NULL;
         }
 
         return g_object_get_data (G_OBJECT (display), "gdm-user-session");
 }
 
 static gboolean
 add_session_record (GdmManager    *manager,
                     GdmSession    *session,
                     GPid           pid,
                     SessionRecord  record)
 {
         const char *username;
-        char *display_name, *hostname, *display_device;
+        char *display_name, *hostname, *display_device, *display_seat_id;
         gboolean recorded = FALSE;
 
         display_name = NULL;
         username = NULL;
         hostname = NULL;
         display_device = NULL;
+        display_seat_id = NULL;
 
         username = gdm_session_get_username (session);
 
         if (username == NULL) {
                 goto out;
         }
 
         g_object_get (G_OBJECT (session),
                       "display-name", &display_name,
                       "display-hostname", &hostname,
                       "display-device", &display_device,
+                      "display-seat-id", &display_seat_id,
                       NULL);
 
         if (display_name == NULL && display_device == NULL) {
-                goto out;
+                if (display_seat_id == NULL)
+                        goto out;
+
+                display_name = g_strdup ("login screen");
+                display_device = g_strdup (display_seat_id);
         }
 
         switch (record) {
             case SESSION_RECORD_LOGIN:
                 gdm_session_record_login (pid,
                                           username,
                                           hostname,
                                           display_name,
                                           display_device);
                 break;
             case SESSION_RECORD_LOGOUT:
                 gdm_session_record_logout (pid,
                                            username,
                                            hostname,
                                            display_name,
                                            display_device);
                 break;
             case SESSION_RECORD_FAILED:
                 gdm_session_record_failed (pid,
                                            username,
                                            hostname,
                                            display_name,
                                            display_device);
                 break;
         }
 
         recorded = TRUE;
 out:
         g_free (display_name);
         g_free (hostname);
         g_free (display_device);
+        g_free (display_seat_id);
 
         return recorded;
 }
 
 static GdmSession *
 find_user_session_for_display (GdmManager *self,
                                GdmDisplay *display)
 {
 
         GList *node = self->priv->user_sessions;
 
         while (node != NULL) {
                 GdmSession *session = node->data;
                 GdmDisplay *candidate_display;
                 GList *next_node = node->next;
 
                 candidate_display = get_display_for_user_session (session);
 
                 if (candidate_display == display)
                         return session;
 
                 node = next_node;
         }
 
         return NULL;
 }
 
 static gboolean
 gdm_manager_handle_register_display (GdmDBusManager        *manager,
                                      GDBusMethodInvocation *invocation,
diff --git a/daemon/gdm-session-record.c b/daemon/gdm-session-record.c
index 7719d0a8..310323b6 100644
--- a/daemon/gdm-session-record.c
+++ b/daemon/gdm-session-record.c
@@ -125,66 +125,70 @@ record_set_host (UTMP       *u,
          */
         if (host_name != NULL
             && x11_display_name != NULL
             && g_str_has_prefix (x11_display_name, ":")) {
                 hostname = g_strdup_printf ("%s%s", host_name, x11_display_name);
         } else {
                 hostname = g_strdup (x11_display_name);
         }
 
         if (hostname != NULL) {
                 memccpy (u->ut_host, hostname, '\0', sizeof (u->ut_host));
                 g_debug ("using ut_host %.*s", (int) sizeof (u->ut_host), u->ut_host);
 #ifdef HAVE_UT_UT_SYSLEN
                 u->ut_syslen = MIN (strlen (hostname), sizeof (u->ut_host));
 #endif
                 g_free (hostname);
         }
 #endif
 }
 
 static void
 record_set_line (UTMP       *u,
                  const char *display_device,
                  const char *x11_display_name)
 {
         /*
          * Set ut_line to the device name associated with this display
          * but remove the "/dev/" prefix.  If no device, then use the
          * $DISPLAY value.
          */
-        if (display_device != NULL
-            && g_str_has_prefix (display_device, "/dev/")) {
+        if (display_device != NULL && g_str_has_prefix (display_device, "/dev/")) {
                 memccpy (u->ut_line,
                          display_device + strlen ("/dev/"),
                          '\0',
                          sizeof (u->ut_line));
+        } else if (display_device != NULL && g_str_has_prefix (display_device, "seat")) {
+                memccpy (u->ut_line,
+                         display_device,
+                         '\0',
+                         sizeof (u->ut_line));
         } else if (x11_display_name != NULL) {
                 memccpy (u->ut_line,
                          x11_display_name,
                          '\0',
                          sizeof (u->ut_line));
         }
 
         g_debug ("using ut_line %.*s", (int) sizeof (u->ut_line), u->ut_line);
 }
 
 void
 gdm_session_record_login (GPid                  session_pid,
                           const char           *user_name,
                           const char           *host_name,
                           const char           *x11_display_name,
                           const char           *display_device)
 {
         UTMP        session_record = { 0 };
 
         if (x11_display_name == NULL)
                 x11_display_name = display_device;
 
         record_set_username (&session_record, user_name);
 
         g_debug ("Writing login record");
 
 #if defined(HAVE_UT_UT_TYPE)
         session_record.ut_type = USER_PROCESS;
         g_debug ("using ut_type USER_PROCESS");
 #endif
-- 
2.31.1