summaryrefslogtreecommitdiff
path: root/debian/patches-applied/pam-loginuid-in-containers
diff options
context:
space:
mode:
authorSteve Langasek <vorlon@debian.org>2014-01-13 19:06:19 -0800
committerSteve Langasek <vorlon@debian.org>2019-01-08 22:11:50 -0800
commit7edd75ed0371cfd9389cacd4275eb603dc53bcf0 (patch)
tree899212ff47e15cbff85ff3214b37fedb7eeb5bdb /debian/patches-applied/pam-loginuid-in-containers
parent95c4d61ea4397ff0e31233afd8fef7e3f7f5f4b2 (diff)
debian/patches-applied/pam-loginuid-in-containers: pam_loginuid:
Ignore failure in user namespaces.
Diffstat (limited to 'debian/patches-applied/pam-loginuid-in-containers')
-rw-r--r--debian/patches-applied/pam-loginuid-in-containers136
1 files changed, 136 insertions, 0 deletions
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 <stgraber@ubuntu.com>
+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 <vorlon@debian.org>
+ Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
+
+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;
+ }
+
+ /*