]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
last: fix phantom detection for unset loginuid and X11 sessions
authorKarel Zak <kzak@redhat.com>
Tue, 28 Apr 2026 11:55:45 +0000 (13:55 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 28 Apr 2026 11:55:45 +0000 (13:55 +0200)
Don't mark a session as phantom when /proc/pid/loginuid exists but
has not been set by pam_loginuid.so (contains the kernel's unset
sentinel value 4294967295).

Skip the /dev/ tty stat() check when the utline starts with ':'
(traditional X11 session registration by xdm/sessreg).

Based on a patch by glangshaw.

Fixes: https://github.com/util-linux/util-linux/issues/4295
Signed-off-by: Karel Zak <kzak@redhat.com>
include/c.h
login-utils/last.c

index 49616389b5c382f8899e57e82381f15f9b148005..c2f8d94ad08ca1e1ca51a3312c56c770aea441e0 100644 (file)
@@ -655,6 +655,10 @@ static inline int fputsln(const char *s, FILE *stream) {
 #define SINT_MIN(t) (-SINT_MAX(t) - (t)1)
 #define MAX_OF_UINT_TYPE(t) ~((t)0)
 
+#ifndef INVALID_UID
+# define INVALID_UID ((uid_t) -1)
+#endif
+
 #ifndef HAVE_REALLOCARRAY
 static inline void *reallocarray(void *ptr, size_t nmemb, size_t size)
 {
index 8b5d64360af06c19f343c2d59e376f74005c65f5..1f5b800c8f659876943150ca6e33e94091559559 100644 (file)
@@ -649,7 +649,7 @@ static int is_phantom(const struct last_control *ctl, struct utmpx *ut)
                if (fscanf(f, "%u", &loginuid) != 1)
                        ret = 1;
                fclose(f);
-               if (!ret && pw->pw_uid != loginuid)
+               if (!ret && loginuid != INVALID_UID && pw->pw_uid != loginuid)
                        return 1;
        } else {
                struct stat st;
@@ -657,11 +657,13 @@ static int is_phantom(const struct last_control *ctl, struct utmpx *ut)
 
                mem2strcpy(utline, ut->ut_line, sizeof(ut->ut_line), sizeof(utline));
 
-               snprintf(path, sizeof(path), "/dev/%s", utline);
-               if (stat(path, &st))
-                       return 1;
-               if (pw->pw_uid != st.st_uid)
-                       return 1;
+               if (utline[0] != ':') {
+                       snprintf(path, sizeof(path), "/dev/%s", utline);
+                       if (stat(path, &st))
+                               return 1;
+                       if (pw->pw_uid != st.st_uid)
+                               return 1;
+               }
        }
        return ret;
 }