last: make session gone determination more robust

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>
This commit is contained in:
Sami Kerola 2014-01-21 22:05:05 +00:00 committed by Karel Zak
parent 098ab0778f
commit 404fa3f93c
1 changed files with 22 additions and 3 deletions

View 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;