From 7edd75ed0371cfd9389cacd4275eb603dc53bcf0 Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Mon, 13 Jan 2014 19:06:19 -0800 Subject: debian/patches-applied/pam-loginuid-in-containers: pam_loginuid: Ignore failure in user namespaces. --- debian/patches-applied/pam-loginuid-in-containers | 136 ++++++++++++++++++++++ debian/patches-applied/series | 1 + 2 files changed, 137 insertions(+) create mode 100644 debian/patches-applied/pam-loginuid-in-containers (limited to 'debian/patches-applied') diff --git a/debian/patches-applied/pam-loginuid-in-containers b/debian/patches-applied/pam-loginuid-in-containers new file mode 100644 index 00000000..bea1e32f --- /dev/null +++ b/debian/patches-applied/pam-loginuid-in-containers @@ -0,0 +1,136 @@ +Author: Stéphane Graber +Description: 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 + +Index: pam.deb/modules/pam_loginuid/pam_loginuid.c +=================================================================== +--- pam.deb.orig/modules/pam_loginuid/pam_loginuid.c ++++ pam.deb/modules/pam_loginuid/pam_loginuid.c +@@ -46,25 +46,49 @@ + + /* + * This function writes the loginuid to the /proc system. It returns +- * 0 on success and 1 on failure. ++ * PAM_SUCCESS on success, ++ * PAM_IGNORE when /proc/self/loginuid does not exist, ++ * PAM_SESSION_ERR in case of any other error. + */ + static int set_loginuid(pam_handle_t *pamh, uid_t uid) + { +- int fd, count, rc = 0; +- char loginuid[24]; ++ 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_WRONLY|O_TRUNC); ++ fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR); + if (fd < 0) { +- if (errno != ENOENT) { +- rc = 1; ++ 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, + "Cannot open /proc/self/loginuid: %m"); + } + return rc; + } +- if (pam_modutil_write(fd, loginuid, count) != count) +- rc = 1; ++ ++ if (pam_modutil_read(fd, buf, sizeof(buf)) == count && ++ memcmp(buf, loginuid, count) == 0) { ++ rc = PAM_SUCCESS; ++ goto done; /* already correct */ ++ } ++ if (lseek(fd, 0, SEEK_SET) == 0 && ftruncate(fd, 0) == 0 && ++ pam_modutil_write(fd, loginuid, count) == count) ++ rc = PAM_SUCCESS; ++ done: + close(fd); + return rc; + } +@@ -164,6 +188,7 @@ + { + const char *user = NULL; + struct passwd *pwd; ++ int ret; + #ifdef HAVE_LIBAUDIT + int require_auditd = 0; + #endif +@@ -182,9 +207,14 @@ + return PAM_SESSION_ERR; + } + +- if (set_loginuid(pamh, pwd->pw_uid)) { +- pam_syslog(pamh, LOG_ERR, "set_loginuid failed\n"); +- return PAM_SESSION_ERR; ++ ret = set_loginuid(pamh, pwd->pw_uid); ++ switch (ret) { ++ case PAM_SUCCESS: ++ case PAM_IGNORE: ++ break; ++ default: ++ pam_syslog(pamh, LOG_ERR, "set_loginuid failed"); ++ return ret; + } + + #ifdef HAVE_LIBAUDIT +@@ -194,11 +224,12 @@ + argv++; + } + +- if (require_auditd) +- return check_auditd(); +- else ++ if (require_auditd) { ++ int rc = check_auditd(); ++ return rc != PAM_SUCCESS ? rc : ret; ++ } else + #endif +- return PAM_SUCCESS; ++ return ret; + } + + /* diff --git a/debian/patches-applied/series b/debian/patches-applied/series index cd9d1997..1c340254 100644 --- a/debian/patches-applied/series +++ b/debian/patches-applied/series @@ -25,3 +25,4 @@ lib_security_multiarch_compat pam_env-fix-overflow.patch pam_env-fix-dos.patch glibc-2_16-compilation-fix.patch +pam-loginuid-in-containers -- cgit v1.2.3