pam_loginuid: make it return PAM_IGNORE in containers

This commit is contained in:
Tomas Mraz 2014-05-22 11:49:12 +02:00
parent 9b30e30268
commit 1368ecb1ca
2 changed files with 157 additions and 1 deletions

View File

@ -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 @@
<para>
<variablelist>
<varlistentry>
+ <term>PAM_SUCCESS</term>
+ <listitem>
+ <para>
+ The loginuid value is set and auditd is running if check requested.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_IGNORE</term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term>PAM_SESSION_ERR</term>
<listitem>
<para>
- An error occurred during session management.
+ Any other error prevented setting loginuid or auditd is not running.
</para>
</listitem>
</varlistentry>
-
</variablelist>
</para>
</refsect1>

View File

@ -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 <tmraz@redhat.com> 1.1.8-11
- pam_loginuid: make it return PAM_IGNORE in containers
* Mon Mar 31 2014 Tomáš Mráz <tmraz@redhat.com> 1.1.8-10
- fix CVE-2014-2583: potential path traversal issue in pam_timestamp