From 086d68f24d984fb48e44aa16aa815825cd5ed0bc Mon Sep 17 00:00:00 2001
From: Jason Pleau <jason@jpleau.ca>
Date: Wed, 30 May 2018 21:48:22 -0400
Subject: [PATCH] daemon/gdm-session-record.c: open/close the utmp database

pututxline() was used without first opening the utxmp database and
without closing it, preventing the logout entry from being fully
committed.

This caused the number of logged-in users to increment after each login,
as logging out did not correctly remove the user login record from utmp.

This commit wraps pututxline() between setutxent() and endutxent(),
making sure that the login/logout operation are fully flushed.

Fixes #381
---
 daemon/gdm-session-record.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/daemon/gdm-session-record.c b/daemon/gdm-session-record.c
index 487f10047..d2df58873 100644
--- a/daemon/gdm-session-record.c
+++ b/daemon/gdm-session-record.c
@@ -186,104 +186,108 @@ gdm_session_record_login (GPid                  session_pid,
 
         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
 
         record_set_timestamp (&session_record);
         record_set_pid (&session_record, session_pid);
         record_set_host (&session_record, x11_display_name, host_name);
         record_set_line (&session_record, display_device, x11_display_name);
 
         /* Handle wtmp */
         g_debug ("Writing wtmp session record to " GDM_NEW_SESSION_RECORDS_FILE);
 #if defined(HAVE_UPDWTMPX)
         updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
 #elif defined(HAVE_UPDWTMP)
         updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
 #elif defined(HAVE_LOGWTMP) && defined(HAVE_UT_UT_HOST)
 #if defined(HAVE_UT_UT_USER)
         logwtmp (session_record.ut_line, session_record.ut_user, session_record.ut_host);
 #elif defined(HAVE_UT_UT_NAME)
         logwtmp (session_record.ut_line, session_record.ut_name, session_record.ut_host);
 #endif
 #endif
 
         /* Handle utmp */
 #if defined(HAVE_GETUTXENT)
         g_debug ("Adding or updating utmp record for login");
+        setutxent();
         pututxline (&session_record);
+        endutxent();
 #elif defined(HAVE_LOGIN)
 	login (&session_record);
 #endif
 }
 
 void
 gdm_session_record_logout (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;
 
         g_debug ("Writing logout record");
 
 #if defined(HAVE_UT_UT_TYPE)
         session_record.ut_type = DEAD_PROCESS;
         g_debug ("using ut_type DEAD_PROCESS");
 #endif
 
         record_set_timestamp (&session_record);
         record_set_pid (&session_record, session_pid);
         record_set_host (&session_record, x11_display_name, host_name);
         record_set_line (&session_record, display_device, x11_display_name);
 
         /* Handle wtmp */
         g_debug ("Writing wtmp logout record to " GDM_NEW_SESSION_RECORDS_FILE);
 #if defined(HAVE_UPDWTMPX)
         updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
 #elif defined (HAVE_UPDWTMP)
         updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
 #elif defined(HAVE_LOGWTMP)
         logwtmp (session_record.ut_line, "", "");
 #endif
 
         /* Handle utmp */
 #if defined(HAVE_GETUTXENT)
         g_debug ("Adding or updating utmp record for logout");
+        setutxent();
         pututxline (&session_record);
+        endutxent();
 #elif defined(HAVE_LOGOUT)
         logout (session_record.ut_line);
 #endif
 }
 
 void
 gdm_session_record_failed (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 failed session attempt record");
 
 #if defined(HAVE_UT_UT_TYPE)
         session_record.ut_type = USER_PROCESS;
         g_debug ("using ut_type USER_PROCESS");
 #endif
 
         record_set_timestamp (&session_record);
         record_set_pid (&session_record, session_pid);
         record_set_host (&session_record, x11_display_name, host_name);
         record_set_line (&session_record, display_device, x11_display_name);
-- 
2.17.1

