vapier      16/02/16 19:03:14

  Modified:             README.history
  Added:               
                        
00_all_0023-CVE-2014-8121-Do-not-close-NSS-files-database-during.patch
                        00_all_0024-Fix-BZ-17905.patch
                        
00_all_0025-Fix-BZ-18985-out-of-range-data-to-strftime-causes-a-.patch
                        00_all_0026-Handle-overflow-in-__hcreate_r.patch
                        
00_all_0027-Improve-check-against-integer-wraparound-in-hcreate_.patch
                        10_all_glibc-CVE-2015-7547.patch
  Log:
  misc upstream fixes

Revision  Changes    Path
1.7                  src/patchsets/glibc/2.21/README.history

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/README.history?rev=1.7&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/README.history?rev=1.7&content-type=text/plain
diff : 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/README.history?r1=1.6&r2=1.7

Index: README.history
===================================================================
RCS file: /var/cvsroot/gentoo/src/patchsets/glibc/2.21/README.history,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- README.history      29 Aug 2015 22:21:52 -0000      1.6
+++ README.history      16 Feb 2016 19:03:14 -0000      1.7
@@ -1,3 +1,11 @@
+6              16 Feb 2015
+       + 00_all_0023-CVE-2014-8121-Do-not-close-NSS-files-database-during.patch
+       + 00_all_0024-Fix-BZ-17905.patch
+       + 00_all_0025-Fix-BZ-18985-out-of-range-data-to-strftime-causes-a-.patch
+       + 00_all_0026-Handle-overflow-in-__hcreate_r.patch
+       + 00_all_0027-Improve-check-against-integer-wraparound-in-hcreate_.patch
+       + 10_all_glibc-CVE-2015-7547.patch
+
 5              29 Aug 2015
        + 00_all_0022-getmntent-fix-memory-corruption-w-blank-lines-BZ-188.patch
 



1.1                  
src/patchsets/glibc/2.21/00_all_0023-CVE-2014-8121-Do-not-close-NSS-files-database-during.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0023-CVE-2014-8121-Do-not-close-NSS-files-database-during.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0023-CVE-2014-8121-Do-not-close-NSS-files-database-during.patch?rev=1.1&content-type=text/plain

Index: 00_all_0023-CVE-2014-8121-Do-not-close-NSS-files-database-during.patch
===================================================================
>From 6d0b7b443c9735672bb76d003c3f7263c5292d7d Mon Sep 17 00:00:00 2001
From: Florian Weimer <[email protected]>
Date: Wed, 29 Apr 2015 14:41:25 +0200
Subject: [PATCH 23/27] CVE-2014-8121: Do not close NSS files database during
 iteration [BZ #18007]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
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.

(cherry picked from commit 03d2730b44cc2236318fd978afa2651753666c55)

Conflicts:
        ChangeLog
        NEWS

(cherry picked from commit e871e19b5f19d2e6595e911b0a5b1c19cda20cc7)
---
 nss/Makefile              |   2 +-
 nss/nss_files/files-XXX.c |   2 +-
 nss/tst-nss-getpwent.c    | 118 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 120 insertions(+), 2 deletions(-)
 create mode 100644 nss/tst-nss-getpwent.c

diff --git a/nss/Makefile b/nss/Makefile
index d419baf..dc351dd 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -39,7 +39,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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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"
-- 
2.6.2




1.1                  src/patchsets/glibc/2.21/00_all_0024-Fix-BZ-17905.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0024-Fix-BZ-17905.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0024-Fix-BZ-17905.patch?rev=1.1&content-type=text/plain

Index: 00_all_0024-Fix-BZ-17905.patch
===================================================================
>From 3e49e0f6236ea20e824fba075aec715dfbec62d3 Mon Sep 17 00:00:00 2001
From: Paul Pluzhnikov <[email protected]>
Date: Sat, 8 Aug 2015 15:53:03 -0700
Subject: [PATCH 24/27] Fix BZ #17905

(cherry picked from commit 0f58539030e436449f79189b6edab17d7479796e)
(cherry picked from commit 907cc11c576a21ea6df5f5ad0a2b1dc3b55dd553)
---
 catgets/Makefile       |  9 ++++++++-
 catgets/catgets.c      | 19 ++++++++++++-------
 catgets/open_catalog.c | 23 ++++++++++++++---------
 catgets/tst-catgets.c  | 31 +++++++++++++++++++++++++++++++
 4 files changed, 65 insertions(+), 17 deletions(-)

diff --git a/catgets/Makefile b/catgets/Makefile
index 4624a88..56de38b 100644
--- a/catgets/Makefile
+++ b/catgets/Makefile
@@ -34,6 +34,7 @@ test-srcs = test-gencat
 ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
                 $(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out
+tests-special += $(objpfx)tst-catgets-mem.out
 endif
 
 gencat-modules = xmalloc
@@ -50,9 +51,11 @@ catgets-CPPFLAGS := 
-DNLSPATH='"$(msgcatdir)/%L/%N:$(msgcatdir)/%L/LC_MESSAGES/%
 
 generated += de.msg test1.cat test1.h test2.cat test2.h sample.SJIS.cat \
             test-gencat.h
+generated += tst-catgets.mtrace tst-catgets-mem.out
+
 generated-dirs += de
 
-tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de
+tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de 
MALLOC_TRACE=$(objpfx)tst-catgets.mtrace
 
 ifeq ($(run-built-tests),yes)
 # This test just checks whether the program produces any error or not.
@@ -86,4 +89,8 @@ $(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat 
\
 $(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat
        $(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@; \
        $(evaluate-test)
+
+$(objpfx)tst-catgets-mem.out: $(objpfx)tst-catgets.out
+       $(common-objpfx)malloc/mtrace $(objpfx)tst-catgets.mtrace > $@; \
+       $(evaluate-test)
 endif
diff --git a/catgets/catgets.c b/catgets/catgets.c
index cf93d56..4be452d 100644
--- a/catgets/catgets.c
+++ b/catgets/catgets.c
@@ -16,7 +16,6 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <alloca.h>
 #include <errno.h>
 #include <locale.h>
 #include <nl_types.h>
@@ -35,6 +34,7 @@ catopen (const char *cat_name, int flag)
   __nl_catd result;
   const char *env_var = NULL;
   const char *nlspath = NULL;
+  char *tmp = NULL;
 
   if (strchr (cat_name, '/') == NULL)
     {
@@ -54,7 +54,10 @@ catopen (const char *cat_name, int flag)
        {
          /* Append the system dependent directory.  */
          size_t len = strlen (nlspath) + 1 + sizeof NLSPATH;
-         char *tmp = alloca (len);
+         tmp = malloc (len);
+
+         if (__glibc_unlikely (tmp == NULL))
+           return (nl_catd) -1;
 
          __stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH);
          nlspath = tmp;
@@ -65,16 +68,18 @@ catopen (const char *cat_name, int flag)
 
   result = (__nl_catd) malloc (sizeof (*result));
   if (result == NULL)
-    /* We cannot get enough memory.  */
-    return (nl_catd) -1;
-
-  if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
+    {
+      /* We cannot get enough memory.  */
+      result = (nl_catd) -1;
+    }
+  else if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
     {
       /* Couldn't open the file.  */
       free ((void *) result);
-      return (nl_catd) -1;
+      result = (nl_catd) -1;
     }
 
+  free (tmp);
   return (nl_catd) result;
 }
 
diff --git a/catgets/open_catalog.c b/catgets/open_catalog.c
index e069416..9f4d776 100644
--- a/catgets/open_catalog.c
+++ b/catgets/open_catalog.c
@@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, const char *nlspath, 
const char *env_var,
   size_t tab_size;
   const char *lastp;
   int result = -1;
+  char *buf = NULL;
 
   if (strchr (cat_name, '/') != NULL || nlspath == NULL)
     fd = open_not_cancel_2 (cat_name, O_RDONLY);
@@ -57,23 +58,23 @@ __open_catalog (const char *cat_name, const char *nlspath, 
const char *env_var,
   if (__glibc_unlikely (bufact + (n) >= bufmax))                             \
     {                                                                        \
       char *old_buf = buf;                                                   \
-      bufmax += 256 + (n);                                                   \
-      buf = (char *) alloca (bufmax);                                        \
-      memcpy (buf, old_buf, bufact);                                         \
+      bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax;                   \
+      buf = realloc (buf, bufmax);                                           \
+      if (__glibc_unlikely (buf == NULL))                                    \
+       {                                                                     \
+         free (old_buf);                                                     \
+         return -1;                                                          \
+       }                                                                     \
     }
 
       /* The RUN_NLSPATH variable contains a colon separated list of
         descriptions where we expect to find catalogs.  We have to
         recognize certain % substitutions and stop when we found the
         first existing file.  */
-      char *buf;
       size_t bufact;
-      size_t bufmax;
+      size_t bufmax = 0;
       size_t len;
 
-      buf = NULL;
-      bufmax = 0;
-
       fd = -1;
       while (*run_nlspath != '\0')
        {
@@ -188,7 +189,10 @@ __open_catalog (const char *cat_name, const char *nlspath, 
const char *env_var,
 
   /* Avoid dealing with directories and block devices */
   if (__builtin_expect (fd, 0) < 0)
-    return -1;
+    {
+      free (buf);
+      return -1;
+    }
 
   if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
     goto close_unlock_return;
@@ -325,6 +329,7 @@ __open_catalog (const char *cat_name, const char *nlspath, 
const char *env_var,
   /* Release the lock again.  */
  close_unlock_return:
   close_not_cancel_no_status (fd);
+  free (buf);
 
   return result;
 }
diff --git a/catgets/tst-catgets.c b/catgets/tst-catgets.c
index a0a4089..140de72 100644
--- a/catgets/tst-catgets.c
+++ b/catgets/tst-catgets.c
@@ -1,7 +1,10 @@
+#include <assert.h>
 #include <mcheck.h>
 #include <nl_types.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/resource.h>
 
 
 static const char *msgs[] =
@@ -12,6 +15,33 @@ static const char *msgs[] =
 };
 #define nmsgs (sizeof (msgs) / sizeof (msgs[0]))
 
+
+/* Test for unbounded alloca.  */
+static int
+do_bz17905 (void)
+{
+  char *buf;
+  struct rlimit rl;
+  nl_catd result;
+
+  const int sz = 1024 * 1024;
+
+  getrlimit (RLIMIT_STACK, &rl);
+  rl.rlim_cur = sz;
+  setrlimit (RLIMIT_STACK, &rl);
+
+  buf = malloc (sz + 1);
+  memset (buf, 'A', sz);
+  buf[sz] = '\0';
+  setenv ("NLSPATH", buf, 1);
+
+  result = catopen (buf, NL_CAT_LOCALE);
+  assert (result == (nl_catd) -1);
+
+  free (buf);
+  return 0;
+}
+
 #define ROUNDS 5
 
 static int
@@ -62,6 +92,7 @@ do_test (void)
        }
     }
 
+  result += do_bz17905 ();
   return result;
 }
 
-- 
2.6.2




1.1                  
src/patchsets/glibc/2.21/00_all_0025-Fix-BZ-18985-out-of-range-data-to-strftime-causes-a-.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0025-Fix-BZ-18985-out-of-range-data-to-strftime-causes-a-.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0025-Fix-BZ-18985-out-of-range-data-to-strftime-causes-a-.patch?rev=1.1&content-type=text/plain

Index: 00_all_0025-Fix-BZ-18985-out-of-range-data-to-strftime-causes-a-.patch
===================================================================
>From 040d72a3aa943de8488870f7db9168d0b6247376 Mon Sep 17 00:00:00 2001
From: Paul Pluzhnikov <[email protected]>
Date: Sat, 26 Sep 2015 13:27:48 -0700
Subject: [PATCH 25/27] Fix BZ #18985 -- out of range data to strftime() causes
 a segfault

(cherry picked from commit d36c75fc0d44deec29635dd239b0fbd206ca49b7)
(cherry picked from commit 163437ec37ea32e82469de9b6cbed0d7209551c1)
---
 time/strftime_l.c   | 20 +++++++++++++-------
 time/tst-strftime.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/time/strftime_l.c b/time/strftime_l.c
index b48ef34..4eb647c 100644
--- a/time/strftime_l.c
+++ b/time/strftime_l.c
@@ -510,13 +510,17 @@ __strftime_internal (s, maxsize, format, tp, tzset_called 
ut_argument
      only a few elements.  Dereference the pointers only if the format
      requires this.  Then it is ok to fail if the pointers are invalid.  */
 # define a_wkday \
-  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
+  ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6                        
     \
+                    ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
 # define f_wkday \
-  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
+  ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6                        
     \
+                    ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
 # define a_month \
-  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
+  ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11                      \
+                    ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
 # define f_month \
-  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
+  ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11                      \
+                    ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
 # define ampm \
   ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11                   \
                                 ? NLW(PM_STR) : NLW(AM_STR)))
@@ -526,8 +530,10 @@ __strftime_internal (s, maxsize, format, tp, tzset_called 
ut_argument
 # define ap_len STRLEN (ampm)
 #else
 # if !HAVE_STRFTIME
-#  define f_wkday (weekday_name[tp->tm_wday])
-#  define f_month (month_name[tp->tm_mon])
+#  define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6  \
+                  ? "?" : weekday_name[tp->tm_wday])
+#  define f_month (tp->tm_mon < 0 || tp->tm_mon > 11   \
+                  ? "?" : month_name[tp->tm_mon])
 #  define a_wkday f_wkday
 #  define a_month f_month
 #  define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
@@ -1321,7 +1327,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called 
ut_argument
                  *tzset_called = true;
                }
 # endif
-             zone = tzname[tp->tm_isdst];
+             zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?";
            }
 #endif
          if (! zone)
diff --git a/time/tst-strftime.c b/time/tst-strftime.c
index 374fba4..af3ff72 100644
--- a/time/tst-strftime.c
+++ b/time/tst-strftime.c
@@ -4,6 +4,56 @@
 #include <time.h>
 
 
+static int
+do_bz18985 (void)
+{
+  char buf[1000];
+  struct tm ttm;
+  int rc, ret = 0;
+
+  memset (&ttm, 1, sizeof (ttm));
+  ttm.tm_zone = NULL;  /* Dereferenced directly if non-NULL.  */
+  rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
+
+  if (rc == 66)
+    {
+      const char expected[]
+       = "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?";
+      if (0 != strcmp (buf, expected))
+       {
+         printf ("expected:\n  %s\ngot:\n  %s\n", expected, buf);
+         ret += 1;
+       }
+    }
+  else
+    {
+      printf ("expected 66, got %d\n", rc);
+      ret += 1;
+    }
+
+  /* Check negative values as well.  */
+  memset (&ttm, 0xFF, sizeof (ttm));
+  ttm.tm_zone = NULL;  /* Dereferenced directly if non-NULL.  */
+  rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
+
+  if (rc == 30)
+    {
+      const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899  ";
+      if (0 != strcmp (buf, expected))
+       {
+         printf ("expected:\n  %s\ngot:\n  %s\n", expected, buf);
+         ret += 1;
+       }
+    }
+  else
+    {
+      printf ("expected 30, got %d\n", rc);
+      ret += 1;
+    }
+
+  return ret;
+}
+
 static struct
 {
   const char *fmt;
@@ -104,7 +154,7 @@ do_test (void)
        }
     }
 
-  return result;
+  return result + do_bz18985 ();
 }
 
 #define TEST_FUNCTION do_test ()
-- 
2.6.2




1.1                  
src/patchsets/glibc/2.21/00_all_0026-Handle-overflow-in-__hcreate_r.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0026-Handle-overflow-in-__hcreate_r.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0026-Handle-overflow-in-__hcreate_r.patch?rev=1.1&content-type=text/plain

Index: 00_all_0026-Handle-overflow-in-__hcreate_r.patch
===================================================================
>From a1e53fd63426c27464ce213833cc1debbe226579 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20B=C3=ADlka?= <[email protected]>
Date: Sat, 11 Jul 2015 17:44:10 +0200
Subject: [PATCH 26/27] Handle overflow in __hcreate_r

Hi,

As in bugzilla entry there is overflow in hsearch when looking for prime
number as SIZE_MAX - 1 is divisible by 5. We fix that by rejecting large
inputs before looking for prime.

        * misc/hsearch_r.c (__hcreate_r): Handle overflow.

(cherry picked from commit 2f5c1750558fe64bac361f52d6827ab1bcfe52bc)
(cherry picked from commit 51e762570e41074a7d9be5b0ee8761f037fc6e68)
---
 misc/hsearch_r.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/misc/hsearch_r.c b/misc/hsearch_r.c
index 3a7c526..8b368cb 100644
--- a/misc/hsearch_r.c
+++ b/misc/hsearch_r.c
@@ -19,7 +19,7 @@
 #include <errno.h>
 #include <malloc.h>
 #include <string.h>
-
+#include <stdint.h>
 #include <search.h>
 
 /* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
@@ -73,6 +73,13 @@ hcreate_r (nel, htab)
       return 0;
     }
 
+  if (nel >= SIZE_MAX / sizeof (_ENTRY))
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
+
   /* There is still another table active. Return with error. */
   if (htab->table != NULL)
     return 0;
-- 
2.6.2




1.1                  
src/patchsets/glibc/2.21/00_all_0027-Improve-check-against-integer-wraparound-in-hcreate_.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0027-Improve-check-against-integer-wraparound-in-hcreate_.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/00_all_0027-Improve-check-against-integer-wraparound-in-hcreate_.patch?rev=1.1&content-type=text/plain

Index: 00_all_0027-Improve-check-against-integer-wraparound-in-hcreate_.patch
===================================================================
>From 8a945f673382756b8559f04bbd2ca8500f914515 Mon Sep 17 00:00:00 2001
From: Florian Weimer <[email protected]>
Date: Thu, 28 Jan 2016 13:59:11 +0100
Subject: [PATCH 27/27] Improve check against integer wraparound in hcreate_r
 [BZ #18240]

(cherry picked from commit bae7c7c764413b23e61cb099ce33be4c4ee259bb)
(cherry picked from commit 965630aefa60ad5f9d8e475ecd8618180f93ec60)
---
 misc/Makefile    |  2 +-
 misc/bug18240.c  | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 misc/hsearch_r.c | 35 +++++++++++++-------------
 3 files changed, 93 insertions(+), 19 deletions(-)
 create mode 100644 misc/bug18240.c

diff --git a/misc/Makefile b/misc/Makefile
index 2f5edf6..12055ce 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -77,7 +77,7 @@ gpl2lgpl := error.c error.h
 
 tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
         tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
-        tst-mntent-blank-corrupt tst-mntent-blank-passno
+        tst-mntent-blank-corrupt tst-mntent-blank-passno bug18240
 ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)tst-error1-mem.out
 endif
diff --git a/misc/bug18240.c b/misc/bug18240.c
new file mode 100644
index 0000000..4b26865
--- /dev/null
+++ b/misc/bug18240.c
@@ -0,0 +1,75 @@
+/* Test integer wraparound in hcreate.
+   Copyright (C) 2016 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <limits.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+test_size (size_t size)
+{
+  int res = hcreate (size);
+  if (res == 0)
+    {
+      if (errno == ENOMEM)
+        return;
+      printf ("error: hcreate (%zu): %m\n", size);
+      exit (1);
+    }
+  char *keys[100];
+  for (int i = 0; i < 100; ++i)
+    {
+      if (asprintf (keys + i, "%d", i) < 0)
+        {
+          printf ("error: asprintf: %m\n");
+          exit (1);
+        }
+      ENTRY e = { keys[i], (char *) "value" };
+      if (hsearch (e, ENTER) == NULL)
+        {
+          printf ("error: hsearch (\"%s\"): %m\n", keys[i]);
+          exit (1);
+        }
+    }
+  hdestroy ();
+
+  for (int i = 0; i < 100; ++i)
+    free (keys[i]);
+}
+
+static int
+do_test (void)
+{
+  test_size (500);
+  test_size (-1);
+  test_size (-3);
+  test_size (INT_MAX - 2);
+  test_size (INT_MAX - 1);
+  test_size (INT_MAX);
+  test_size (((unsigned) INT_MAX) + 1);
+  test_size (UINT_MAX - 2);
+  test_size (UINT_MAX - 1);
+  test_size (UINT_MAX);
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/misc/hsearch_r.c b/misc/hsearch_r.c
index 8b368cb..91fa63f 100644
--- a/misc/hsearch_r.c
+++ b/misc/hsearch_r.c
@@ -46,15 +46,12 @@ static int
 isprime (unsigned int number)
 {
   /* no even number will be passed */
-  unsigned int div = 3;
-
-  while (div * div < number && number % div != 0)
-    div += 2;
-
-  return number % div != 0;
+  for (unsigned int div = 3; div <= number / div; div += 2)
+    if (number % div == 0)
+      return 0;
+  return 1;
 }
 
-
 /* Before using the hash table we must allocate memory for it.
    Test for an existing table are done. We allocate one element
    more as the found prime number says. This is done for more effective
@@ -73,13 +70,6 @@ hcreate_r (nel, htab)
       return 0;
     }
 
-  if (nel >= SIZE_MAX / sizeof (_ENTRY))
-    {
-      __set_errno (ENOMEM);
-      return 0;
-    }
-
-
   /* There is still another table active. Return with error. */
   if (htab->table != NULL)
     return 0;
@@ -88,10 +78,19 @@ hcreate_r (nel, htab)
      use will not work.  */
   if (nel < 3)
     nel = 3;
-  /* Change nel to the first prime number not smaller as nel. */
-  nel |= 1;      /* make odd */
-  while (!isprime (nel))
-    nel += 2;
+
+  /* Change nel to the first prime number in the range [nel, UINT_MAX - 2],
+     The '- 2' means 'nel += 2' cannot overflow.  */
+  for (nel |= 1; ; nel += 2)
+    {
+      if (UINT_MAX - 2 < nel)
+       {
+         __set_errno (ENOMEM);
+         return 0;
+       }
+      if (isprime (nel))
+       break;
+    }
 
   htab->size = nel;
   htab->filled = 0;
-- 
2.6.2




1.1                  src/patchsets/glibc/2.21/10_all_glibc-CVE-2015-7547.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/10_all_glibc-CVE-2015-7547.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/glibc/2.21/10_all_glibc-CVE-2015-7547.patch?rev=1.1&content-type=text/plain

Index: 10_all_glibc-CVE-2015-7547.patch
===================================================================
https://bugs.gentoo.org/574880
https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html

--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *answer, int 
anslen, const char *qname,
   int h_namelen = 0;
 
   if (ancount == 0)
-    return NSS_STATUS_NOTFOUND;
+    {
+      *h_errnop = HOST_NOT_FOUND;
+      return NSS_STATUS_NOTFOUND;
+    }
 
   while (ancount-- > 0 && cp < end_of_message && had_error == 0)
     {
@@ -1208,7 +1211,14 @@ gaih_getanswer_slice (const querybuf *answer, int 
anslen, const char *qname,
   /* Special case here: if the resolver sent a result but it only
      contains a CNAME while we are looking for a T_A or T_AAAA record,
      we fail with NOTFOUND instead of TRYAGAIN.  */
-  return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
+  if (canon != NULL)
+    {
+      *h_errnop = HOST_NOT_FOUND;
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  *h_errnop = NETDB_INTERNAL;
+  return NSS_STATUS_TRYAGAIN;
 }
 
 
@@ -1242,8 +1252,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, 
const querybuf *answer2,
                                                     &pat, &buffer, &buflen,
                                                     errnop, h_errnop, ttlp,
                                                     &first);
+      /* Use the second response status in some cases.  */
       if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
        status = status2;
+      /* Do not return a truncated second response (unless it was
+         unavoidable e.g. unrecoverable TRYAGAIN).  */
+      if (status == NSS_STATUS_SUCCESS
+         && (status2 == NSS_STATUS_TRYAGAIN
+             && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
+       status = NSS_STATUS_TRYAGAIN;
     }
 
   return status;
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
                  {
                    free (*answerp2);
                    *answerp2 = NULL;
+                   *nanswerp2 = 0;
                    *answerp2_malloced = 0;
                  }
        }
@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp,
                          {
                            free (*answerp2);
                            *answerp2 = NULL;
+                           *nanswerp2 = 0;
                            *answerp2_malloced = 0;
                          }
 
@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp,
          {
            free (*answerp2);
            *answerp2 = NULL;
+           *nanswerp2 = 0;
            *answerp2_malloced = 0;
          }
        if (saved_herrno != -1)
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -639,11 +639,7 @@ send_vc(res_state statp,
 {
        const HEADER *hp = (HEADER *) buf;
        const HEADER *hp2 = (HEADER *) buf2;
-       u_char *ans = *ansp;
-       int orig_anssizp = *anssizp;
-       // XXX REMOVE
-       // int anssiz = *anssizp;
-       HEADER *anhp = (HEADER *) ans;
+       HEADER *anhp = (HEADER *) *ansp;
        struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
        int truncating, connreset, n;
        /* On some architectures compiler might emit a warning indicating
@@ -767,35 +763,6 @@ send_vc(res_state statp,
                assert (anscp != NULL || ansp2 == NULL);
                thisresplenp = &resplen;
        } else {
-               if (*anssizp != MAXPACKET) {
-                       /* No buffer allocated for the first
-                          reply.  We can try to use the rest
-                          of the user-provided buffer.  */
-#if __GNUC_PREREQ (4, 7)
-                       DIAG_PUSH_NEEDS_COMMENT;
-                       DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
-#endif
-#if _STRING_ARCH_unaligned
-                       *anssizp2 = orig_anssizp - resplen;
-                       *ansp2 = *ansp + resplen;
-#else
-                       int aligned_resplen
-                         = ((resplen + __alignof__ (HEADER) - 1)
-                            & ~(__alignof__ (HEADER) - 1));
-                       *anssizp2 = orig_anssizp - aligned_resplen;
-                       *ansp2 = *ansp + aligned_resplen;
-#endif
-#if __GNUC_PREREQ (4, 7)
-                       DIAG_POP_NEEDS_COMMENT;
-#endif
-               } else {
-                       /* The first reply did not fit into the
-                          user-provided buffer.  Maybe the second
-                          answer will.  */
-                       *anssizp2 = orig_anssizp;
-                       *ansp2 = *ansp;
-               }
-
                thisanssizp = anssizp2;
                thisansp = ansp2;
                thisresplenp = resplen2;
@@ -804,10 +771,14 @@ send_vc(res_state statp,
        anhp = (HEADER *) *thisansp;
 
        *thisresplenp = rlen;
-       if (rlen > *thisanssizp) {
-               /* Yes, we test ANSCP here.  If we have two buffers
-                  both will be allocatable.  */
-               if (__glibc_likely (anscp != NULL))       {
+       /* Is the answer buffer too small?  */
+       if (*thisanssizp < rlen) {
+               /* If the current buffer is not the the static
+                  user-supplied buffer then we can reallocate
+                  it.  */
+               if (thisansp != NULL && thisansp != ansp) {
+                       /* Always allocate MAXPACKET, callers expect
+                          this specific size.  */
                        u_char *newp = malloc (MAXPACKET);
                        if (newp == NULL) {
                                *terrno = ENOMEM;
@@ -957,8 +928,6 @@ send_dg(res_state statp,
 {
        const HEADER *hp = (HEADER *) buf;
        const HEADER *hp2 = (HEADER *) buf2;
-       u_char *ans = *ansp;
-       int orig_anssizp = *anssizp;
        struct timespec now, timeout, finish;
        struct pollfd pfd[1];
        int ptimeout;
@@ -1154,50 +1123,48 @@ send_dg(res_state statp,
                        assert (anscp != NULL || ansp2 == NULL);
                        thisresplenp = &resplen;
                } else {
-                       if (*anssizp != MAXPACKET) {
-                               /* No buffer allocated for the first
-                                  reply.  We can try to use the rest
-                                  of the user-provided buffer.  */
-#if _STRING_ARCH_unaligned
-                               *anssizp2 = orig_anssizp - resplen;
-                               *ansp2 = *ansp + resplen;
-#else
-                               int aligned_resplen
-                                 = ((resplen + __alignof__ (HEADER) - 1)
-                                    & ~(__alignof__ (HEADER) - 1));
-                               *anssizp2 = orig_anssizp - aligned_resplen;
-                               *ansp2 = *ansp + aligned_resplen;
-#endif
-                       } else {
-                               /* The first reply did not fit into the
-                                  user-provided buffer.  Maybe the second
-                                  answer will.  */
-                               *anssizp2 = orig_anssizp;
-                               *ansp2 = *ansp;
-                       }
-
                        thisanssizp = anssizp2;
                        thisansp = ansp2;
                        thisresplenp = resplen2;
                }
 
                if (*thisanssizp < MAXPACKET
-                   /* Yes, we test ANSCP here.  If we have two buffers
-                      both will be allocatable.  */
-                   && anscp
+                   /* If the current buffer is not the the static
+                      user-supplied buffer then we can reallocate
+                      it.  */
+                   && (thisansp != NULL && thisansp != ansp)
 #ifdef FIONREAD
+                   /* Is the size too small?  */
                    && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
                        || *thisanssizp < *thisresplenp)
 #endif
                     ) {
+                       /* Always allocate MAXPACKET, callers expect
+                          this specific size.  */
                        u_char *newp = malloc (MAXPACKET);
                        if (newp != NULL) {
-                               *anssizp = MAXPACKET;
-                               *thisansp = ans = newp;
+                               *thisanssizp = MAXPACKET;
+                               *thisansp = newp;
                                if (thisansp == ansp2)
                                  *ansp2_malloced = 1;
                        }
                }
+               /* We could end up with truncation if anscp was NULL
+                  (not allowed to change caller's buffer) and the
+                  response buffer size is too small.  This isn't a
+                  reliable way to detect truncation because the ioctl
+                  may be an inaccurate report of the UDP message size.
+                  Therefore we use this only to issue debug output.
+                  To do truncation accurately with UDP we need
+                  MSG_TRUNC which is only available on Linux.  We
+                  can abstract out the Linux-specific feature in the
+                  future to detect truncation.  */
+               if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
+                       Dprint(statp->options & RES_DEBUG,
+                              (stdout, ";; response may be truncated (UDP)\n")
+                       );
+               }
+
                HEADER *anhp = (HEADER *) *thisansp;
                socklen_t fromlen = sizeof(struct sockaddr_in6);
                assert (sizeof(from) <= fromlen);




Reply via email to