]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
last: make session gone determination more robust
authorSami Kerola <kerolasa@iki.fi>
Tue, 21 Jan 2014 22:05:05 +0000 (22:05 +0000)
committerKarel Zak <kzak@redhat.com>
Mon, 10 Feb 2014 17:25:31 +0000 (18:25 +0100)
Earlier determination that used kill with signal zero to pid was prone to
false positive reports, due reuse of pid space and unrelated processes.
New function is_phantom() tries do a little bit better job, but fails to
be perfect.  It seems linking to gether utmp session start time or
terminal id with /proc/<pid>/ information is not as simple as one might
hope.

Reported-by: Karel Zak <kzak@redhat.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
login-utils/last.c

index 5550dcb3f5bb5881f846fb2b10b9fc0442babd25..e4a8497765fd9a6db09b8da67c66fa170f03b7b8 100644 (file)
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <utmp.h>
+#include <pwd.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
@@ -572,6 +573,26 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
        exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 }
 
+static int is_phantom(struct utmp *ut)
+{
+       struct passwd *pw;
+       char path[32];
+       FILE *f;
+       unsigned int loginuid, ret = 0;
+
+       pw = getpwnam(ut->ut_name);
+       if (!pw)
+               return 1;
+       sprintf(path, "/proc/%u/loginuid", ut->ut_pid);
+       if (!(f = fopen(path, "r")))
+               return 1;
+       if (fscanf(f, "%u", &loginuid) != 1)
+               ret = 1;
+       fclose(f);
+       if (!ret && pw->pw_uid != loginuid)
+               return 1;
+       return ret;
+}
 
 static void process_wtmp_file(const struct last_control *ctl)
 {
@@ -766,9 +787,7 @@ static void process_wtmp_file(const struct last_control *ctl)
                                if (!lastboot) {
                                        c = R_NOW;
                                        /* Is process still alive? */
-                                       if (ut.ut_pid > 0 &&
-                                           kill(ut.ut_pid, 0) != 0 &&
-                                           errno == ESRCH)
+                                       if (is_phantom(&ut))
                                                c = R_PHANTOM;
                                } else
                                        c = whydown;