From 24f3a88e7de52fbfcb7b8a1ebdae0cdbef420edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Tue, 7 Jan 2014 16:12:03 -0800 Subject: pam_loginuid: Ignore failure in user namespaces When running pam_loginuid in a container using the user namespaces, even uid 0 isn't allowed to set the loginuid property. This change catches the EACCES from opening loginuid, checks if the user is in the host namespace (by comparing the uid_map with the host's one) and only if that's the case, sets rc to 1. Should uid_map not exist or be unreadable for some reason, it'll be assumed that the process is running on the host's namespace. The initial reason behind this change was failure to ssh into an unprivileged container (using a 3.13 kernel and current LXC) when using a standard pam profile for sshd (which requires success from pam_loginuid). I believe this solution doesn't have any drawback and will allow people to use unprivileged containers normally. An alternative would be to have all distros set pam_loginuid as optional but that'd be bad for any of the other potential failure case which people may care about. There has also been some discussions to get some of the audit features tied with the user namespaces but currently none of that has been merged upstream and the currently proposed implementation doesn't cover loginuid (nor is it clear how this should even work when loginuid is set as immutable after initial write). Signed-off-by: Steve Langasek Signed-off-by: Dmitry V. Levin --- modules/pam_loginuid/pam_loginuid.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'modules/pam_loginuid') diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c index 96f8ffa5..54ae6f07 100644 --- a/modules/pam_loginuid/pam_loginuid.c +++ b/modules/pam_loginuid/pam_loginuid.c @@ -55,13 +55,26 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid) { int fd, count, rc = PAM_SESSION_ERR; char loginuid[24], buf[24]; + static const char host_uid_map[] = " 0 0 4294967295\n"; + char uid_map[sizeof(host_uid_map)]; count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid); fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR); if (fd < 0) { if (errno == ENOENT) { rc = PAM_IGNORE; - } else { + } else if (errno == EACCES) { + fd = open("/proc/self/uid_map", O_RDONLY); + if (fd >= 0) { + count = pam_modutil_read(fd, uid_map, sizeof(uid_map)); + if (strncmp(uid_map, host_uid_map, count) != 0) + rc = PAM_IGNORE; + close(fd); + } + if (rc != PAM_IGNORE) + errno = EACCES; + } + if (rc != PAM_IGNORE) { pam_syslog(pamh, LOG_ERR, "Cannot open /proc/self/loginuid: %m"); } -- cgit v1.2.3