diff options
author | Sami Kerola | 2014-08-12 00:04:26 +0200 |
---|---|---|
committer | Sami Kerola | 2014-09-19 20:31:01 +0200 |
commit | 8813da1ea2d42776c98943617e673d9cf8ec8a77 (patch) | |
tree | 29be53f400c5451ccb6849a35b7563552306fa56 /login-utils/last.c | |
parent | lib: remove xgetpass() (diff) | |
download | kernel-qcow2-util-linux-8813da1ea2d42776c98943617e673d9cf8ec8a77.tar.gz kernel-qcow2-util-linux-8813da1ea2d42776c98943617e673d9cf8ec8a77.tar.xz kernel-qcow2-util-linux-8813da1ea2d42776c98943617e673d9cf8ec8a77.zip |
last: make is_phantom() when kernel config does not include audit support
When kernel CONFIG_AUDIT is not set the /proc/<pid>/loginuid information
is not present resulting live sessions to be marked 'gone - no logout' in
last(1) print out. To go-around this change makes last(1) to look
/dev/<tty> device ownership as a substitute of loginuid.
The go-around seems to work fairly well, but it has it short comings.
For example after closing a X window session the /dev/ttyN file seems to
be owned by root, not the user who had it before entering to the X
session. While that is suboptimal it is still better than an attmempt to
determine uid_t by looking owner of the /proc/<struct utmp ut_pid>, that
is a login(1) process running as root.
The issue was found using Archlinux installation.
$ pacman -Qi linux
Name : linux
Version : 3.16-2
[...]
Build Date : Mon Aug 4 18:06:51 2014
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Diffstat (limited to 'login-utils/last.c')
-rw-r--r-- | login-utils/last.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/login-utils/last.c b/login-utils/last.c index f7a2576f4..fb82f31c0 100644 --- a/login-utils/last.c +++ b/login-utils/last.c @@ -582,8 +582,6 @@ static int is_phantom(const struct last_control *ctl, struct utmp *ut) { struct passwd *pw; char path[32]; - FILE *f = NULL; - unsigned int loginuid; int ret = 0; if (ut->UL_UT_TIME < ctl->boot_time.tv_sec) @@ -592,14 +590,26 @@ static int is_phantom(const struct last_control *ctl, struct utmp *ut) if (!pw) return 1; sprintf(path, "/proc/%u/loginuid", ut->ut_pid); - if (access(path, R_OK) != 0 || !(f = fopen(path, "r"))) - return 1; + if (access(path, R_OK) == 0) { + unsigned int loginuid; + FILE *f = NULL; + + 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; + } else { + struct stat st; - if (fscanf(f, "%u", &loginuid) != 1) - ret = 1; - fclose(f); - if (!ret && pw->pw_uid != loginuid) - return 1; + sprintf(path, "/dev/%s", ut->ut_line); + if (stat(path, &st)) + return 1; + if (pw->pw_uid != st.st_uid) + return 1; + } return ret; } |