From 2e62d5aea3f5ac267cfa54f0ea1f8c07ac85a95a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= Date: Fri, 17 Jan 2014 18:24:16 -0500 Subject: pam_loginuid: Always return PAM_IGNORE in userns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous patch to support user namespaces works fine with containers that are started from a desktop/terminal session but fails when dealing with containers that were started from a remote session such as ssh. I haven't looked at the exact reason for that in the kernel but on the userspace side of things, the difference is that containers started from an ssh session will happily let pam open /proc/self/loginuid read-write, will let it read its content but will then fail with EPERM when trying to write to it. So to make the userns support bullet proof, this commit moves the userns check earlier in the function (which means a small performance impact as it'll now happen everytime on kernels that have userns support) and will set rc = PAM_IGNORE instead of rc = PAM_ERROR. The rest of the code is still executed in the event that PAM is run on a future kernel where we have some kind of audit namespace that includes a working loginuid. Signed-off-by: Stéphane Graber Signed-off-by: Steve Langasek Signed-off-by: Dmitry V. Levin --- modules/pam_loginuid/pam_loginuid.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'modules') diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c index 54ae6f07..d2584228 100644 --- a/modules/pam_loginuid/pam_loginuid.c +++ b/modules/pam_loginuid/pam_loginuid.c @@ -58,21 +58,22 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid) static const char host_uid_map[] = " 0 0 4294967295\n"; char uid_map[sizeof(host_uid_map)]; + /* loginuid in user namespaces currently isn't writable and in some + case, not even readable, so consider any failure as ignorable (but try + anyway, in case we hit a kernel which supports it). */ + 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); + } + 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 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, -- cgit v1.2.3