diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix index 9a451d48cbcf..cf356ccefbed 100644 --- a/pkgs/development/libraries/glibc/common.nix +++ b/pkgs/development/libraries/glibc/common.nix @@ -56,6 +56,11 @@ stdenv.mkDerivation ({ "/bin:/usr/bin", which is inappropriate on NixOS machines. This patch extends the search path by "/run/current-system/sw/bin". */ ./fix_path_attribute_in_getconf.patch + + ./security-4a28f4d5.patch + ./security-bdf1ff05.patch + ./cve-2014-8121.patch + ./cve-2015-1781.patch ]; postPatch = diff --git a/pkgs/development/libraries/glibc/cve-2014-8121.patch b/pkgs/development/libraries/glibc/cve-2014-8121.patch new file mode 100644 index 000000000000..95a86259dba8 --- /dev/null +++ b/pkgs/development/libraries/glibc/cve-2014-8121.patch @@ -0,0 +1,230 @@ +From 03d2730b44cc2236318fd978afa2651753666c55 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 29 Apr 2015 14:41:25 +0200 +Subject: [PATCH] CVE-2014-8121: Do not close NSS files database during + iteration [BZ #18007] +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Robin Hack discovered Samba would enter an infinite loop processing +certain quota-related requests. We eventually tracked this down to a +glibc issue. + +Running a (simplified) test case under strace shows that /etc/passwd +is continuously opened and closed: + +… +open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 +lseek(3, 0, SEEK_CUR) = 0 +read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717 +lseek(3, 2717, SEEK_SET) = 2717 +close(3) = 0 +open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 +lseek(3, 0, SEEK_CUR) = 0 +lseek(3, 0, SEEK_SET) = 0 +read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717 +lseek(3, 2717, SEEK_SET) = 2717 +close(3) = 0 +open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 +lseek(3, 0, SEEK_CUR) = 0 +… + +The lookup function implementation in +nss/nss_files/files-XXX.c:DB_LOOKUP has code to prevent that. It is +supposed skip closing the input file if it was already open. + + /* Reset file pointer to beginning or open file. */ \ + status = internal_setent (keep_stream); \ + \ + if (status == NSS_STATUS_SUCCESS) \ + { \ + /* Tell getent function that we have repositioned the file pointer. */ \ + last_use = getby; \ + \ + while ((status = internal_getent (result, buffer, buflen, errnop \ + H_ERRNO_ARG EXTRA_ARGS_VALUE)) \ + == NSS_STATUS_SUCCESS) \ + { break_if_match } \ + \ + if (! keep_stream) \ + internal_endent (); \ + } \ + +keep_stream is initialized from the stayopen flag in internal_setent. +internal_setent is called from the set*ent implementation as: + + status = internal_setent (stayopen); + +However, for non-host database, this flag is always 0, per the +STAYOPEN magic in nss/getXXent_r.c. + +Thus, the fix is this: + +- status = internal_setent (stayopen); ++ status = internal_setent (1); + +This is not a behavioral change even for the hosts database (where the +application can specify the stayopen flag) because with a call to +sethostent(0), the file handle is still not closed in the +implementation of gethostent. +--- + ChangeLog | 8 ++++ + NEWS | 12 +++-- + nss/Makefile | 2 +- + nss/nss_files/files-XXX.c | 2 +- + nss/tst-nss-getpwent.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 136 insertions(+), 6 deletions(-) + create mode 100644 nss/tst-nss-getpwent.c + +diff --git a/nss/Makefile b/nss/Makefile +index d75dad2..65ab7b5 100644 +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -47,7 +47,7 @@ install-bin := getent makedb + makedb-modules = xmalloc hash-string + extra-objs += $(makedb-modules:=.o) + +-tests = test-netdb tst-nss-test1 test-digits-dots ++tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent + xtests = bug-erange + + # Specify rules for the nss_* modules. We have some services. +diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c +index a7a45e5..a7ce5ea 100644 +--- a/nss/nss_files/files-XXX.c ++++ b/nss/nss_files/files-XXX.c +@@ -134,7 +134,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stayopen) + + __libc_lock_lock (lock); + +- status = internal_setent (stayopen); ++ status = internal_setent (1); + + if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) + { +diff --git a/nss/tst-nss-getpwent.c b/nss/tst-nss-getpwent.c +new file mode 100644 +index 0000000..f2e8abc +--- /dev/null ++++ b/nss/tst-nss-getpwent.c +@@ -0,0 +1,118 @@ ++/* Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++int ++do_test (void) ++{ ++ /* Count the number of entries in the password database, and fetch ++ data from the first and last entries. */ ++ size_t count = 0; ++ struct passwd * pw; ++ char *first_name = NULL; ++ uid_t first_uid = 0; ++ char *last_name = NULL; ++ uid_t last_uid = 0; ++ setpwent (); ++ while ((pw = getpwent ()) != NULL) ++ { ++ if (first_name == NULL) ++ { ++ first_name = strdup (pw->pw_name); ++ if (first_name == NULL) ++ { ++ printf ("strdup: %m\n"); ++ return 1; ++ } ++ first_uid = pw->pw_uid; ++ } ++ ++ free (last_name); ++ last_name = strdup (pw->pw_name); ++ if (last_name == NULL) ++ { ++ printf ("strdup: %m\n"); ++ return 1; ++ } ++ last_uid = pw->pw_uid; ++ ++count; ++ } ++ endpwent (); ++ ++ if (count == 0) ++ { ++ printf ("No entries in the password database.\n"); ++ return 0; ++ } ++ ++ /* Try again, this time interleaving with name-based and UID-based ++ lookup operations. The counts do not match if the interleaved ++ lookups affected the enumeration. */ ++ size_t new_count = 0; ++ setpwent (); ++ while ((pw = getpwent ()) != NULL) ++ { ++ if (new_count == count) ++ { ++ printf ("Additional entry in the password database.\n"); ++ return 1; ++ } ++ ++new_count; ++ struct passwd *pw2 = getpwnam (first_name); ++ if (pw2 == NULL) ++ { ++ printf ("getpwnam (%s) failed: %m\n", first_name); ++ return 1; ++ } ++ pw2 = getpwnam (last_name); ++ if (pw2 == NULL) ++ { ++ printf ("getpwnam (%s) failed: %m\n", last_name); ++ return 1; ++ } ++ pw2 = getpwuid (first_uid); ++ if (pw2 == NULL) ++ { ++ printf ("getpwuid (%llu) failed: %m\n", ++ (unsigned long long) first_uid); ++ return 1; ++ } ++ pw2 = getpwuid (last_uid); ++ if (pw2 == NULL) ++ { ++ printf ("getpwuid (%llu) failed: %m\n", ++ (unsigned long long) last_uid); ++ return 1; ++ } ++ } ++ endpwent (); ++ if (new_count < count) ++ { ++ printf ("Missing entry in the password database.\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" + diff --git a/pkgs/development/libraries/glibc/cve-2015-1781.patch b/pkgs/development/libraries/glibc/cve-2015-1781.patch new file mode 100644 index 000000000000..6831d5ac7426 --- /dev/null +++ b/pkgs/development/libraries/glibc/cve-2015-1781.patch @@ -0,0 +1,27 @@ +From 2959eda9272a033863c271aff62095abd01bd4e3 Mon Sep 17 00:00:00 2001 +From: Arjun Shankar +Date: Tue, 21 Apr 2015 14:06:31 +0200 +Subject: [PATCH] CVE-2015-1781: resolv/nss_dns/dns-host.c buffer overflow + [BZ#18287] + +--- + ChangeLog | 6 ++++++ + NEWS | 9 ++++++++- + resolv/nss_dns/dns-host.c | 3 ++- + 3 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index b16b0dd..d8c5579 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, + int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; +- if (__glibc_unlikely (buflen < sizeof (struct host_data) + pad)) ++ buflen = buflen > pad ? buflen - pad : 0; ++ if (__glibc_unlikely (buflen < sizeof (struct host_data))) + { + /* The buffer is too small. */ + too_small: + diff --git a/pkgs/development/libraries/glibc/security-4a28f4d5.patch b/pkgs/development/libraries/glibc/security-4a28f4d5.patch new file mode 100644 index 000000000000..25f994d859c1 --- /dev/null +++ b/pkgs/development/libraries/glibc/security-4a28f4d5.patch @@ -0,0 +1,53 @@ +From 4a28f4d55a6cc33474c0792fe93b5942d81bf185 Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Thu, 26 Feb 2015 14:55:24 +0100 +Subject: [PATCH] Fix read past end of pattern in fnmatch (bug 18032) + +--- + ChangeLog | 7 +++++++ + NEWS | 2 +- + posix/fnmatch_loop.c | 5 ++--- + posix/tst-fnmatch3.c | 8 +++++--- + 4 files changed, 15 insertions(+), 7 deletions(-) + +diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c +index c0cb2fc..72c5d8f 100644 +--- a/posix/fnmatch_loop.c ++++ b/posix/fnmatch_loop.c +@@ -945,14 +945,13 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) + } + else if (c == L('[') && *p == L('.')) + { +- ++p; + while (1) + { + c = *++p; +- if (c == '\0') ++ if (c == L('\0')) + return FNM_NOMATCH; + +- if (*p == L('.') && p[1] == L(']')) ++ if (c == L('.') && p[1] == L(']')) + break; + } + p += 2; +diff --git a/posix/tst-fnmatch3.c b/posix/tst-fnmatch3.c +index d27a557..75bc00a 100644 +--- a/posix/tst-fnmatch3.c ++++ b/posix/tst-fnmatch3.c +@@ -21,9 +21,11 @@ + int + do_test (void) + { +- const char *pattern = "[[:alpha:]'[:alpha:]\0]"; +- +- return fnmatch (pattern, "a", 0) != FNM_NOMATCH; ++ if (fnmatch ("[[:alpha:]'[:alpha:]\0]", "a", 0) != FNM_NOMATCH) ++ return 1; ++ if (fnmatch ("[a[.\0.]]", "a", 0) != FNM_NOMATCH) ++ return 1; ++ return 0; + } + + #define TEST_FUNCTION do_test () + diff --git a/pkgs/development/libraries/glibc/security-bdf1ff05.patch b/pkgs/development/libraries/glibc/security-bdf1ff05.patch new file mode 100644 index 000000000000..b4175694f912 --- /dev/null +++ b/pkgs/development/libraries/glibc/security-bdf1ff05.patch @@ -0,0 +1,39 @@ +From bdf1ff052a8e23d637f2c838fa5642d78fcedc33 Mon Sep 17 00:00:00 2001 +From: Paul Pluzhnikov +Date: Sun, 22 Feb 2015 12:01:47 -0800 +Subject: [PATCH] Fix BZ #17269 -- _IO_wstr_overflow integer overflow + +--- + ChangeLog | 6 ++++++ + NEWS | 6 +++--- + libio/wstrops.c | 8 +++++++- + 3 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/libio/wstrops.c b/libio/wstrops.c +index 43d847d..3993579 100644 +--- a/libio/wstrops.c ++++ b/libio/wstrops.c +@@ -95,8 +95,11 @@ _IO_wstr_overflow (fp, c) + wchar_t *old_buf = fp->_wide_data->_IO_buf_base; + size_t old_wblen = _IO_wblen (fp); + _IO_size_t new_size = 2 * old_wblen + 100; +- if (new_size < old_wblen) ++ ++ if (__glibc_unlikely (new_size < old_wblen) ++ || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t))) + return EOF; ++ + new_buf + = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size + * sizeof (wchar_t)); +@@ -186,6 +189,9 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) + return 1; + + _IO_size_t newsize = offset + 100; ++ if (__glibc_unlikely (newsize > SIZE_MAX / sizeof (wchar_t))) ++ return 1; ++ + wchar_t *oldbuf = wd->_IO_buf_base; + wchar_t *newbuf + = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize +