From 1368ecb1ca2ef02213a06d8ed1e76dd20eef72c1 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 22 May 2014 11:49:12 +0200 Subject: [PATCH] pam_loginuid: make it return PAM_IGNORE in containers --- pam-1.1.8-loginuid-container.patch | 151 +++++++++++++++++++++++++++++ pam.spec | 7 +- 2 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 pam-1.1.8-loginuid-container.patch diff --git a/pam-1.1.8-loginuid-container.patch b/pam-1.1.8-loginuid-container.patch new file mode 100644 index 0000000..278829a --- /dev/null +++ b/pam-1.1.8-loginuid-container.patch @@ -0,0 +1,151 @@ +diff -up Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c.container Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c +--- Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c.container 2013-06-18 16:11:21.000000000 +0200 ++++ Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c 2014-01-27 17:24:53.000000000 +0100 +@@ -47,25 +47,56 @@ + + /* + * 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)]; ++ ++ /* 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_WRONLY|O_TRUNC); ++ fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR); + if (fd < 0) { +- if (errno != ENOENT) { +- rc = 1; +- pam_syslog(pamh, LOG_ERR, +- "Cannot open /proc/self/loginuid: %m"); ++ if (errno == ENOENT) { ++ rc = PAM_IGNORE; ++ } ++ if (rc != PAM_IGNORE) { ++ pam_syslog(pamh, LOG_ERR, "Cannot open %s: %m", ++ "/proc/self/loginuid"); + } + return rc; + } +- if (pam_modutil_write(fd, loginuid, count) != count) +- rc = 1; ++ ++ count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid); ++ 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; ++ } else { ++ if (rc != PAM_IGNORE) { ++ pam_syslog(pamh, LOG_ERR, "Error writing %s: %m", ++ "/proc/self/loginuid"); ++ } ++ } ++ done: + close(fd); + return rc; + } +@@ -165,6 +196,7 @@ _pam_loginuid(pam_handle_t *pamh, int fl + { + const char *user = NULL; + struct passwd *pwd; ++ int ret; + #ifdef HAVE_LIBAUDIT + int require_auditd = 0; + #endif +@@ -183,9 +215,14 @@ _pam_loginuid(pam_handle_t *pamh, int fl + 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 +@@ -195,11 +232,12 @@ _pam_loginuid(pam_handle_t *pamh, int fl + 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 -up Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.8.xml.container Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.8.xml +--- Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.8.xml.container 2013-06-18 16:11:21.000000000 +0200 ++++ Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.8.xml 2014-05-22 11:33:14.000000000 +0200 +@@ -69,14 +69,31 @@ + + + ++ PAM_SUCCESS ++ ++ ++ The loginuid value is set and auditd is running if check requested. ++ ++ ++ ++ ++ PAM_IGNORE ++ ++ ++ The /proc/self/loginuid file is not present on the system or the ++ login process runs inside uid namespace and kernel does not support ++ overwriting loginuid. ++ ++ ++ ++ + PAM_SESSION_ERR + + +- An error occurred during session management. ++ Any other error prevented setting loginuid or auditd is not running. + + + +- + + + diff --git a/pam.spec b/pam.spec index 930e340..10c8b3a 100644 --- a/pam.spec +++ b/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.1.8 -Release: 10%{?dist} +Release: 11%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ # - this option is redundant as the BSD license allows that anyway. # pam_timestamp, pam_loginuid, and pam_console modules are GPLv2+. @@ -47,6 +47,7 @@ Patch33: pam-1.1.8-translation-updates.patch Patch34: pam-1.1.8-canonicalize-username.patch Patch35: pam-1.1.8-cve-2013-7041.patch Patch36: pam-1.1.8-cve-2014-2583.patch +Patch37: pam-1.1.8-loginuid-container.patch %define _pamlibdir %{_libdir} %define _moduledir %{_libdir}/security @@ -127,6 +128,7 @@ mv pam-redhat-%{pam_redhat_version}/* modules %patch34 -p1 -b .canonicalize %patch35 -p1 -b .case %patch36 -p1 -b .timestamp-ruser +%patch37 -p1 -b .container %build autoreconf -i @@ -375,6 +377,9 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Thu May 22 2014 Tomáš Mráz 1.1.8-11 +- pam_loginuid: make it return PAM_IGNORE in containers + * Mon Mar 31 2014 Tomáš Mráz 1.1.8-10 - fix CVE-2014-2583: potential path traversal issue in pam_timestamp