[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#764540: wheezy-pu: package glibc/2.13-38+deb7u5



Package: release.debian.org
Severity: normal
Tags: wheezy
User: release.debian.org@packages.debian.org
Usertags: pu

Dear release managers,

I would like to do an update of eglibc in wheezy, with the patches we
have accumulated in the SVN over the last months. I understand that
it's a bit late with the stable release schedule, that said all this
patches have been upstream and in jessie/sid for months.

This version fixes a regression introduced by the recent security
uploads, a stack overflow that the security team hasn't consider it 
serious enough to warrant a DSA, and two annoying issues already fixed
in jessie/sid for which users asked for a backport. Here is the
corresponding changelog:

| eglibc (2.13-38+deb7u5) wheezy; urgency=medium
| 
|   * debian/patches/any/cvs-resolv-reuse-fd.diff: new patch from upstream
|     to fix invalid file descriptor reuse while sending DNS query.  Closes:
|     #722075, #756343.

This is a single line fix to reload a variable instead of keeping it
initialized to the previous value. This bug got more attention now that
more people use golang.

|   * debian/patches/any/cvs-CVE-2013-4357.diff: new patch from upstream to
|     fix stack overflow issues. Closes: #742925.

This is yet another fix for stack overflow issues in the GNU libc, that
have been missed in the previous CVEs. The idea is to not use alloca on
bug amount of memory and either to fail or to use malloc instead.

|   * debian/patches/any/submitted-CVE-2014-0475.diff: update from upstream
|     to fix a localplt regression introduced in version 2.13-38+deb7u3.

This is a very small patch to not access memmem through PLT for internal
usage. See https://sourceware.org/glibc/wiki/Testing/Check-localplt

|   * patches/any/cvs-dlopen-tls-memleak.patch: new patch from upstream to
|     fix a memory leak with dlopen() and thread-local storage variables.
|     Closes: #763559.

This patch fixes a memory leak happening mostly when loading a C++
library with dlopen().

|  -- Aurelien Jarno <aurel32@debian.org>  Wed, 08 Oct 2014 22:50:01 +0200

You will find the full debdiff from the latest security update below.

Thanks for considering.

Aurelien



diff -u eglibc-2.13/debian/changelog eglibc-2.13/debian/changelog
--- eglibc-2.13/debian/changelog
+++ eglibc-2.13/debian/changelog
@@ -1,3 +1,18 @@
+eglibc (2.13-38+deb7u5) wheezy; urgency=medium
+
+  * debian/patches/any/cvs-resolv-reuse-fd.diff: new patch from upstream
+    to fix invalid file descriptor reuse while sending DNS query.  Closes:
+    #722075, #756343.
+  * debian/patches/any/cvs-CVE-2013-4357.diff: new patch from upstream to
+    fix stack overflow issues. Closes: #742925.
+  * debian/patches/any/submitted-CVE-2014-0475.diff: update from upstream
+    to fix a localplt regression introduced in version 2.13-38+deb7u3.
+  * patches/any/cvs-dlopen-tls-memleak.patch: new patch from upstream to
+    fix a memory leak with dlopen() and thread-local storage variables.
+    Closes: #763559.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Wed, 08 Oct 2014 22:50:01 +0200
+
 eglibc (2.13-38+deb7u4) wheezy-security; urgency=high
 
   * Apply upstream patch to fix buffer overflow in __gconv_translit_find.
diff -u eglibc-2.13/debian/patches/series eglibc-2.13/debian/patches/series
--- eglibc-2.13/debian/patches/series
+++ eglibc-2.13/debian/patches/series
@@ -393,0 +394,3 @@
+any/cvs-resolv-reuse-fd.diff
+any/cvs-CVE-2013-4357.diff
+any/cvs-dlopen-tls-memleak.patch
diff -u eglibc-2.13/debian/patches/any/submitted-CVE-2014-0475.diff eglibc-2.13/debian/patches/any/submitted-CVE-2014-0475.diff
--- eglibc-2.13/debian/patches/any/submitted-CVE-2014-0475.diff
+++ eglibc-2.13/debian/patches/any/submitted-CVE-2014-0475.diff
@@ -123,0 +124,20 @@
+--- a/include/string.h
++++ b/include/string.h
+@@ -86,6 +86,7 @@ libc_hidden_proto (__strtok_r)
+ extern char *__strsep_g (char **__stringp, __const char *__delim);
+ libc_hidden_proto (__strsep_g)
+ libc_hidden_proto (strnlen)
++libc_hidden_proto (memmem)
+ 
+ libc_hidden_builtin_proto (memchr)
+ libc_hidden_builtin_proto (memcpy)
+--- a/string/memmem.c
++++ b/string/memmem.c
+@@ -74,5 +74,6 @@ memmem (const void *haystack_start, size_t haystack_len,
+   else
+     return two_way_long_needle (haystack, haystack_len, needle, needle_len);
+ }
++libc_hidden_def (memmem)
+ 
+ #undef LONG_NEEDLE_THRESHOLD
+
--- eglibc-2.13.orig/debian/patches/any/cvs-dlopen-tls-memleak.patch
+++ eglibc-2.13/debian/patches/any/cvs-dlopen-tls-memleak.patch
@@ -0,0 +1,142 @@
+2011-04-10  Ulrich Drepper  <drepper@gmail.com>
+
+	[BZ #12650]
+	* sysdeps/i386/dl-tls.h: Define TLS_DTV_UNALLOCATED.
+	* sysdeps/ia64/dl-tls.h: Likewise.
+	* sysdeps/powerpc/dl-tls.h: Likewise.
+	* sysdeps/s390/dl-tls.h: Likewise.
+	* sysdeps/sh/dl-tls.h: Likewise.
+	* sysdeps/sparc/dl-tls.h: Likewise.
+	* sysdeps/x86_64/dl-tls.h: Likewise.
+	* elf/dl-tls.c: Don't define TLS_DTV_UNALLOCATED here.
+
+nptl/
+2011-04-10  Ulrich Drepper  <drepper@gmail.com>
+
+	[BZ #12650]
+	* allocatestack.c (get_cached_stack): Deallocate DTV entries before
+	clearing memory.
+	Patch partly by Robert Rex <robert.rex@exasol.com>.
+
+ports/
+2011-04-11  Joseph Myers  <joseph@codesourcery.com>
+
+	* sysdeps/arm/dl-tls.h (TLS_DTV_UNALLOCATED): Define.
+	* sysdeps/mips/dl-tls.h (TLS_DTV_UNALLOCATED): Define.
+
+
+--- a/elf/dl-tls.c
++++ b/elf/dl-tls.c
+@@ -33,9 +33,6 @@
+    to allow dynamic loading of modules defining IE-model TLS data.  */
+ #define TLS_STATIC_SURPLUS	64 + DL_NNS * 100
+ 
+-/* Value used for dtv entries for which the allocation is delayed.  */
+-#define TLS_DTV_UNALLOCATED	((void *) -1l)
+-
+ 
+ /* Out-of-memory handler.  */
+ #ifdef SHARED
+--- a/nptl/allocatestack.c
++++ b/nptl/allocatestack.c
+@@ -26,6 +26,7 @@
+ #include <sys/mman.h>
+ #include <sys/param.h>
+ #include <dl-sysdep.h>
++#include <dl-tls.h>
+ #include <tls.h>
+ #include <list.h>
+ #include <lowlevellock.h>
+@@ -242,6 +243,10 @@
+ 
+   /* Clear the DTV.  */
+   dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
++  for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
++    if (! dtv[1 + cnt].pointer.is_static
++	&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
++      free (dtv[1 + cnt].pointer.val);
+   memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
+ 
+   /* Re-initialize the TLS.  */
+--- a/sysdeps/i386/dl-tls.h
++++ b/sysdeps/i386/dl-tls.h
+@@ -58,3 +58,6 @@
+ 
+ # endif
+ #endif
++
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
+--- a/sysdeps/ia64/dl-tls.h
++++ b/sysdeps/ia64/dl-tls.h
+@@ -28,3 +28,6 @@
+ #define DONT_USE_TLS_INDEX	1
+ 
+ extern void *__tls_get_addr (size_t m, size_t offset);
++
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
+--- a/sysdeps/powerpc/dl-tls.h
++++ b/sysdeps/powerpc/dl-tls.h
+@@ -50,4 +50,7 @@
+ # define __TLS_GET_ADDR(__ti)	(__tls_get_addr (__ti) - TLS_DTV_OFFSET)
+ #endif
+ 
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
++
+ #endif /* dl-tls.h */
+--- a/sysdeps/s390/dl-tls.h
++++ b/sysdeps/s390/dl-tls.h
+@@ -75,3 +75,6 @@
+      + (unsigned long) __builtin_thread_pointer (); }) 
+ 
+ #endif
++
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
+--- a/sysdeps/sh/dl-tls.h
++++ b/sysdeps/sh/dl-tls.h
+@@ -27,3 +27,6 @@
+ 
+ 
+ extern void *__tls_get_addr (tls_index *ti);
++
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
+--- a/sysdeps/sparc/dl-tls.h
++++ b/sysdeps/sparc/dl-tls.h
+@@ -27,3 +27,6 @@
+ 
+ 
+ extern void *__tls_get_addr (tls_index *ti);
++
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
+--- a/sysdeps/x86_64/dl-tls.h
++++ b/sysdeps/x86_64/dl-tls.h
+@@ -27,3 +27,6 @@
+ 
+ 
+ extern void *__tls_get_addr (tls_index *ti);
++
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
+--- a/ports/sysdeps/arm/dl-tls.h
++++ b/ports/sysdeps/arm/dl-tls.h
+@@ -27,3 +27,6 @@
+ 
+ 
+ extern void *__tls_get_addr (tls_index *ti);
++
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
+--- a/ports/sysdeps/mips/dl-tls.h
++++ b/ports/sysdeps/mips/dl-tls.h
+@@ -44,3 +44,6 @@
+ 
+ # define GET_ADDR_OFFSET	(ti->ti_offset + TLS_DTV_OFFSET)
+ # define __TLS_GET_ADDR(__ti)	(__tls_get_addr (__ti) - TLS_DTV_OFFSET)
++
++/* Value used for dtv entries for which the allocation is delayed.  */
++#define TLS_DTV_UNALLOCATED	((void *) -1l)
--- eglibc-2.13.orig/debian/patches/any/cvs-CVE-2013-4357.diff
+++ eglibc-2.13/debian/patches/any/cvs-CVE-2013-4357.diff
@@ -0,0 +1,849 @@
+2011-05-22  Ulrich Drepper  <drepper@gmail.com>
+ 
+	[BZ #12671]
+	* nis/nss_nis/nis-alias.c (_nss_nis_getaliasbyname_r): Use malloc in
+	some situations.
+	* nscd/nscd_getserv_r.c (nscd_getserv_r): Likewise.
+	* posix/glob.c (glob_in_dir): Take additional parameter alloca_used.
+	add in in __libc_use_alloca calls.  Adjust callers.
+	(glob): Use malloc in some situations.
+
+--- a/nis/nss_nis/nis-alias.c
++++ b/nis/nss_nis/nis-alias.c
+@@ -142,10 +142,10 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer,
+       int yperr;
+ 
+       if (new_start)
+-        yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
++	yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
+ 			  &len);
+       else
+-        yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
++	yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
+ 			 &keylen, &result, &len);
+ 
+       if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+@@ -153,20 +153,20 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer,
+ 	  enum nss_status retval = yperr2nss (yperr);
+ 
+ 	  if (retval == NSS_STATUS_TRYAGAIN)
+-            *errnop = errno;
+-          return retval;
+-        }
++	    *errnop = errno;
++	  return retval;
++	}
+ 
+       if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+-        {
++	{
+ 	  free (result);
+-          *errnop = ERANGE;
+-          return NSS_STATUS_TRYAGAIN;
+-        }
++	  *errnop = ERANGE;
++	  return NSS_STATUS_TRYAGAIN;
++	}
+       char *p = strncpy (buffer, result, len);
+       buffer[len] = '\0';
+       while (isspace (*p))
+-        ++p;
++	++p;
+       free (result);
+ 
+       parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer,
+@@ -213,13 +213,25 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
+       return NSS_STATUS_UNAVAIL;
+     }
+ 
+-  size_t namlen = strlen (name);
+-  char name2[namlen + 1];
+-
+   char *domain;
+   if (__builtin_expect (yp_get_default_domain (&domain), 0))
+     return NSS_STATUS_UNAVAIL;
+ 
++  size_t namlen = strlen (name);
++  char *name2;
++  int use_alloca = __libc_use_alloca (namlen + 1);
++  if (use_alloca)
++    name2 = __alloca (namlen + 1);
++  else
++    {
++      name2 = malloc (namlen + 1);
++      if (name2 == NULL)
++	{
++	  *errnop = ENOMEM;
++	  return NSS_STATUS_TRYAGAIN;
++	}
++    }
++
+   /* Convert name to lowercase.  */
+   size_t i;
+   for (i = 0; i < namlen; ++i)
+@@ -230,6 +242,9 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
+   int len;
+   int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len);
+ 
++  if (!use_alloca)
++    free (name2);
++
+   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+     {
+       enum nss_status retval = yperr2nss (yperr);
+--- a/nscd/nscd_getserv_r.c
++++ b/nscd/nscd_getserv_r.c
+@@ -17,6 +17,7 @@
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+    02111-1307 USA.  */
+ 
++#include <assert.h>
+ #include <errno.h>
+ #include <string.h>
+ #include <not-cancel.h>
+@@ -80,6 +81,7 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
+ {
+   int gc_cycle;
+   int nretries = 0;
++  size_t alloca_used = 0;
+ 
+   /* If the mapping is available, try to search there instead of
+      communicating with the nscd.  */
+@@ -88,13 +90,23 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
+ 			       &gc_cycle);
+   size_t protolen = proto == NULL ? 0 : strlen (proto);
+   size_t keylen = critlen + 1 + protolen + 1;
+-  char *key = alloca (keylen);
++  int alloca_key = __libc_use_alloca (keylen);
++  char *key;
++  if (alloca_key)
++    key = alloca_account (keylen, alloca_used);
++  else
++    {
++      key = malloc (keylen);
++      if (key == NULL)
++	return -1;
++    }
+   memcpy (__mempcpy (__mempcpy (key, crit, critlen),
+ 		     "/", 1), proto ?: "", protolen + 1);
+ 
+  retry:;
+   const char *s_name = NULL;
+   const char *s_proto = NULL;
++  int alloca_aliases_len = 0;
+   const uint32_t *aliases_len = NULL;
+   const char *aliases_list = NULL;
+   int retval = -1;
+@@ -136,8 +148,22 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
+ 	  if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
+ 	      != 0)
+ 	    {
+-	      uint32_t *tmp = alloca (serv_resp.s_aliases_cnt
+-				      * sizeof (uint32_t));
++	      uint32_t *tmp;
++	      alloca_aliases_len
++		= __libc_use_alloca (alloca_used
++				     + (serv_resp.s_aliases_cnt
++					* sizeof (uint32_t)));
++	      if (alloca_aliases_len)
++		tmp = __alloca (serv_resp.s_aliases_cnt * sizeof (uint32_t));
++	      else
++		{
++		  tmp = malloc (serv_resp.s_aliases_cnt * sizeof (uint32_t));
++		  if (tmp == NULL)
++		    {
++		      retval = ENOMEM;
++		      goto out;
++		    }
++		}
+ 	      aliases_len = memcpy (tmp, aliases_len,
+ 				    serv_resp.s_aliases_cnt
+ 				    * sizeof (uint32_t));
+@@ -217,8 +243,24 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
+ 
+ 	  if (serv_resp.s_aliases_cnt > 0)
+ 	    {
+-	      aliases_len = alloca (serv_resp.s_aliases_cnt
+-				    * sizeof (uint32_t));
++	      assert (alloca_aliases_len == 0);
++	      alloca_aliases_len
++		= __libc_use_alloca (alloca_used
++				     + (serv_resp.s_aliases_cnt
++					* sizeof (uint32_t)));
++	      if (alloca_aliases_len)
++		aliases_len = alloca (serv_resp.s_aliases_cnt
++				      * sizeof (uint32_t));
++	      else
++		{
++		  aliases_len = malloc (serv_resp.s_aliases_cnt
++					* sizeof (uint32_t));
++		  if (aliases_len == NULL)
++		    {
++		      retval = ENOMEM;
++		      goto out_close;
++		    }
++		}
+ 	      vec[n].iov_base = (void *) aliases_len;
+ 	      vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t);
+ 
+@@ -329,5 +371,10 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
+ 	goto retry;
+     }
+ 
++  if (!alloca_aliases_len)
++    free ((void *) aliases_len);
++  if (!alloca_key)
++    free (key);
++
+   return retval;
+ }
+--- a/posix/glob.c
++++ b/posix/glob.c
+@@ -199,7 +199,7 @@ static const char *next_brace_sub (const char *begin, int flags) __THROW;
+ 
+ static int glob_in_dir (const char *pattern, const char *directory,
+ 			int flags, int (*errfunc) (const char *, int),
+-			glob_t *pglob);
++			glob_t *pglob, size_t alloca_used);
+ extern int __glob_pattern_type (const char *pattern, int quote)
+     attribute_hidden;
+ 
+@@ -253,13 +253,18 @@ glob (pattern, flags, errfunc, pglob)
+      glob_t *pglob;
+ {
+   const char *filename;
+-  const char *dirname;
++  char *dirname = NULL;
+   size_t dirlen;
+   int status;
+   size_t oldcount;
+   int meta;
+   int dirname_modified;
++  int malloc_dirname = 0;
+   glob_t dirs;
++  int retval = 0;
++#ifdef _LIBC
++  size_t alloca_used = 0;
++#endif
+ 
+   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
+     {
+@@ -308,20 +313,26 @@ glob (pattern, flags, errfunc, pglob)
+ 	  const char *next;
+ 	  const char *rest;
+ 	  size_t rest_len;
+-#ifdef __GNUC__
+-	  char onealt[strlen (pattern) - 1];
+-#else
+-	  char *onealt = (char *) malloc (strlen (pattern) - 1);
+-	  if (onealt == NULL)
++	  char *onealt;
++	  size_t pattern_len = strlen (pattern) - 1;
++#ifdef _LIBC
++	  int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
++	  if (alloca_onealt)
++	    onealt = alloca_account (pattern_len, alloca_used);
++	  else
++#endif
+ 	    {
+-	      if (!(flags & GLOB_APPEND))
++	      onealt = (char *) malloc (pattern_len);
++	      if (onealt == NULL)
+ 		{
+-		  pglob->gl_pathc = 0;
+-		  pglob->gl_pathv = NULL;
++		  if (!(flags & GLOB_APPEND))
++		    {
++		      pglob->gl_pathc = 0;
++		      pglob->gl_pathv = NULL;
++		    }
++		  return GLOB_NOSPACE;
+ 		}
+-	      return GLOB_NOSPACE;
+ 	    }
+-#endif
+ 
+ 	  /* We know the prefix for all sub-patterns.  */
+ 	  alt_start = mempcpy (onealt, pattern, begin - pattern);
+@@ -332,9 +343,11 @@ glob (pattern, flags, errfunc, pglob)
+ 	  if (next == NULL)
+ 	    {
+ 	      /* It is an illegal expression.  */
+-#ifndef __GNUC__
+-	      free (onealt);
++	    illegal_brace:
++#ifdef _LIBC
++	      if (__builtin_expect (!alloca_onealt, 0))
+ #endif
++		free (onealt);
+ 	      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+ 	    }
+ 
+@@ -344,13 +357,8 @@ glob (pattern, flags, errfunc, pglob)
+ 	    {
+ 	      rest = next_brace_sub (rest + 1, flags);
+ 	      if (rest == NULL)
+-		{
+-		  /* It is an illegal expression.  */
+-#ifndef __GNUC__
+-		  free (onealt);
+-#endif
+-		  return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+-		}
++		/* It is an illegal expression.  */
++		goto illegal_brace;
+ 	    }
+ 	  /* Please note that we now can be sure the brace expression
+ 	     is well-formed.  */
+@@ -386,9 +394,10 @@ glob (pattern, flags, errfunc, pglob)
+ 	      /* If we got an error, return it.  */
+ 	      if (result && result != GLOB_NOMATCH)
+ 		{
+-#ifndef __GNUC__
+-		  free (onealt);
++#ifdef _LIBC
++		  if (__builtin_expect (!alloca_onealt, 0))
+ #endif
++		    free (onealt);
+ 		  if (!(flags & GLOB_APPEND))
+ 		    {
+ 		      globfree (pglob);
+@@ -406,9 +415,10 @@ glob (pattern, flags, errfunc, pglob)
+ 	      assert (next != NULL);
+ 	    }
+ 
+-#ifndef __GNUC__
+-	  free (onealt);
++#ifdef _LIBC
++	  if (__builtin_expect (!alloca_onealt, 0))
+ #endif
++	    free (onealt);
+ 
+ 	  if (pglob->gl_pathc != firstc)
+ 	    /* We found some entries.  */
+@@ -455,7 +465,7 @@ glob (pattern, flags, errfunc, pglob)
+ 	 case is nothing but a notation for a directory.  */
+       if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
+ 	{
+-	  dirname = pattern;
++	  dirname = (char *) pattern;
+ 	  dirlen = strlen (pattern);
+ 
+ 	  /* Set FILENAME to NULL as a special flag.  This is ugly but
+@@ -473,9 +483,9 @@ glob (pattern, flags, errfunc, pglob)
+ 
+ 	  filename = pattern;
+ #ifdef _AMIGA
+-	  dirname = "";
++	  dirname = (char *) "";
+ #else
+-	  dirname = ".";
++	  dirname = (char *) ".";
+ #endif
+ 	  dirlen = 0;
+ 	}
+@@ -485,7 +495,7 @@ glob (pattern, flags, errfunc, pglob)
+ 	       && (flags & GLOB_NOESCAPE) == 0))
+     {
+       /* "/pattern" or "\\/pattern".  */
+-      dirname = "/";
++      dirname = (char *) "/";
+       dirlen = 1;
+       ++filename;
+     }
+@@ -511,7 +521,17 @@ glob (pattern, flags, errfunc, pglob)
+ 	     from "d:/", since "d:" and "d:/" are not the same.*/
+ 	}
+ #endif
+-      newp = (char *) __alloca (dirlen + 1);
++#ifdef _LIBC
++      if (__libc_use_alloca (alloca_used + dirlen + 1))
++	newp = alloca_account (dirlen + 1, alloca_used);
++      else
++#endif
++	{
++	  newp = malloc (dirlen + 1);
++	  if (newp == NULL)
++	    return GLOB_NOSPACE;
++	  malloc_dirname = 1;
++	}
+       *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
+       dirname = newp;
+       ++filename;
+@@ -551,7 +571,8 @@ glob (pattern, flags, errfunc, pglob)
+ 	      oldcount = pglob->gl_pathc + pglob->gl_offs;
+ 	      goto no_matches;
+ 	    }
+-	  return val;
++	  retval = val;
++	  goto out;
+ 	}
+     }
+ 
+@@ -563,7 +584,8 @@ glob (pattern, flags, errfunc, pglob)
+ 	      && (dirname[2] == '\0' || dirname[2] == '/')))
+ 	{
+ 	  /* Look up home directory.  */
+-	  const char *home_dir = getenv ("HOME");
++	  char *home_dir = getenv ("HOME");
++	  int malloc_home_dir = 0;
+ # ifdef _AMIGA
+ 	  if (home_dir == NULL || home_dir[0] == '\0')
+ 	    home_dir = "SYS:";
+@@ -582,7 +604,7 @@ glob (pattern, flags, errfunc, pglob)
+ 		/* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
+ 		   a moderate value.  */
+ 		buflen = 20;
+-	      name = (char *) __alloca (buflen);
++	      name = alloca_account (buflen, alloca_used);
+ 
+ 	      success = getlogin_r (name, buflen) == 0;
+ 	      if (success)
+@@ -592,6 +614,7 @@ glob (pattern, flags, errfunc, pglob)
+ 		  long int pwbuflen = GETPW_R_SIZE_MAX ();
+ 		  char *pwtmpbuf;
+ 		  struct passwd pwbuf;
++		  int malloc_pwtmpbuf = 0;
+ 		  int save = errno;
+ 
+ #     ifndef _LIBC
+@@ -600,7 +623,18 @@ glob (pattern, flags, errfunc, pglob)
+ 		       Try a moderate value.  */
+ 		    pwbuflen = 1024;
+ #     endif
+-		  pwtmpbuf = (char *) __alloca (pwbuflen);
++		  if (__libc_use_alloca (alloca_used + pwbuflen))
++		    pwtmpbuf = alloca_account (pwbuflen, alloca_used);
++		  else
++		    {
++		      pwtmpbuf = malloc (pwbuflen);
++		      if (pwtmpbuf == NULL)
++			{
++			  retval = GLOB_NOSPACE;
++			  goto out;
++			}
++		      malloc_pwtmpbuf = 1;
++		    }
+ 
+ 		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+ 			 != 0)
+@@ -610,47 +644,116 @@ glob (pattern, flags, errfunc, pglob)
+ 			  p = NULL;
+ 			  break;
+ 			}
+-#     ifdef _LIBC
+-		      pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen,
++
++		      if (!malloc_pwtmpbuf
++			  && __libc_use_alloca (alloca_used
++						+ 2 * pwbuflen))
++			pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
++							  2 * pwbuflen,
++							  alloca_used);
++		      else
++			{
++			  char *newp = realloc (malloc_pwtmpbuf
++						? pwtmpbuf : NULL,
+ 						2 * pwbuflen);
+-#     else
+-		      pwbuflen *= 2;
+-		      pwtmpbuf = (char *) __alloca (pwbuflen);
+-#     endif
++			  if (newp == NULL)
++			    {
++			      if (__builtin_expect (malloc_pwtmpbuf, 0))
++				free (pwtmpbuf);
++			      retval = GLOB_NOSPACE;
++			      goto out;
++			    }
++			  pwtmpbuf = newp;
++			  pwbuflen = 2 * pwbuflen;
++			  malloc_pwtmpbuf = 1;
++			}
+ 		      __set_errno (save);
+ 		    }
+ #    else
+ 		  p = getpwnam (name);
+ #    endif
+ 		  if (p != NULL)
+-		    home_dir = p->pw_dir;
++		    {
++		      if (!malloc_pwtmpbuf)
++			home_dir = p->pw_dir;
++		      else
++			{
++			  size_t home_dir_len = strlen (p->pw_dir) + 1;
++			  if (__libc_use_alloca (alloca_used + home_dir_len))
++			    home_dir = alloca_account (home_dir_len,
++						       alloca_used);
++			  else
++			    {
++			      home_dir = malloc (home_dir_len);
++			      if (home_dir == NULL)
++				{
++				  free (pwtmpbuf);
++				  retval = GLOB_NOSPACE;
++				  goto out;
++				}
++			      malloc_home_dir = 1;
++			    }
++			  memcpy (home_dir, p->pw_dir, home_dir_len);
++
++			  free (pwtmpbuf);
++			}
++		    }
+ 		}
+ 	    }
+ #   endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */
+ 	  if (home_dir == NULL || home_dir[0] == '\0')
+ 	    {
+ 	      if (flags & GLOB_TILDE_CHECK)
+-		return GLOB_NOMATCH;
++		{
++		  if (__builtin_expect (malloc_home_dir, 0))
++		    free (home_dir);
++		  retval = GLOB_NOMATCH;
++		  goto out;
++		}
+ 	      else
+-		home_dir = "~"; /* No luck.  */
++		home_dir = (char *) "~"; /* No luck.  */
+ 	    }
+ #  endif /* WINDOWS32 */
+ # endif
+ 	  /* Now construct the full directory.  */
+ 	  if (dirname[1] == '\0')
+ 	    {
++	      if (__builtin_expect (malloc_dirname, 0))
++		free (dirname);
++
+ 	      dirname = home_dir;
+ 	      dirlen = strlen (dirname);
++	      malloc_dirname = malloc_home_dir;
+ 	    }
+ 	  else
+ 	    {
+ 	      char *newp;
+ 	      size_t home_len = strlen (home_dir);
+-	      newp = (char *) __alloca (home_len + dirlen);
++	      int use_alloca = __libc_use_alloca (alloca_used
++						  + home_len + dirlen);
++	      if (use_alloca)
++		newp = alloca_account (home_len + dirlen, alloca_used);
++	      else
++		{
++		  newp = malloc (home_len + dirlen);
++		  if (newp == NULL)
++		    {
++		      if (__builtin_expect (malloc_home_dir, 0))
++			free (home_dir);
++		      retval = GLOB_NOSPACE;
++		      goto out;
++		    }
++		}
++
+ 	      mempcpy (mempcpy (newp, home_dir, home_len),
+ 		       &dirname[1], dirlen);
++
++	      if (__builtin_expect (malloc_dirname, 0))
++		free (dirname);
++
+ 	      dirname = newp;
+ 	      dirlen += home_len - 1;
++	      malloc_dirname = !use_alloca;
+ 	    }
+ 	  dirname_modified = 1;
+ 	}
+@@ -657,7 +760,8 @@ glob (pattern, flags, errfunc, pglob)
+       else
+ 	{
+ 	  char *end_name = strchr (dirname, '/');
+-	  const char *user_name;
++	  char *user_name;
++	  int malloc_user_name = 0;
+ 	  const char *home_dir;
+ 	  char *unescape = NULL;
+ 
+@@ -677,7 +781,18 @@ glob (pattern, flags, errfunc, pglob)
+ 	  else
+ 	    {
+ 	      char *newp;
+-	      newp = (char *) __alloca (end_name - dirname);
++	      if (__libc_use_alloca (alloca_used + (end_name - dirname)))
++		newp = alloca_account (end_name - dirname, alloca_used);
++	      else
++		{
++		  newp = malloc (end_name - dirname);
++		  if (newp == NULL)
++		    {
++		      retval = GLOB_NOSPACE;
++		      goto out;
++		    }
++		  malloc_user_name = 1;
++		}
+ 	      if (unescape != NULL)
+ 		{
+ 		  char *p = mempcpy (newp, dirname + 1,
+@@ -714,6 +829,7 @@ glob (pattern, flags, errfunc, pglob)
+ #  if defined HAVE_GETPWNAM_R || defined _LIBC
+ 	    long int buflen = GETPW_R_SIZE_MAX ();
+ 	    char *pwtmpbuf;
++	    int malloc_pwtmpbuf = 0;
+ 	    struct passwd pwbuf;
+ 	    int save = errno;
+ 
+@@ -723,7 +839,21 @@ glob (pattern, flags, errfunc, pglob)
+ 		 moderate value.  */
+ 	      buflen = 1024;
+ #   endif
+-	    pwtmpbuf = (char *) __alloca (buflen);
++	    if (__libc_use_alloca (alloca_used + buflen))
++	      pwtmpbuf = alloca_account (buflen, alloca_used);
++	    else
++	      {
++		pwtmpbuf = malloc (buflen);
++		if (pwtmpbuf == NULL)
++		  {
++		  nomem_getpw:
++		    if (__builtin_expect (malloc_user_name, 0))
++		      free (user_name);
++		    retval = GLOB_NOSPACE;
++		    goto out;
++		  }
++		malloc_pwtmpbuf = 1;
++	      }
+ 
+ 	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+ 	      {
+@@ -732,40 +862,77 @@ glob (pattern, flags, errfunc, pglob)
+ 		    p = NULL;
+ 		    break;
+ 		  }
+-#   ifdef _LIBC
+-		pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen);
+-#   else
+-		buflen *= 2;
+-		pwtmpbuf = __alloca (buflen);
+-#   endif
++		if (!malloc_pwtmpbuf
++		    && __libc_use_alloca (alloca_used + 2 * buflen))
++		  pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
++						    2 * buflen, alloca_used);
++		else
++		  {
++		    char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
++					  2 * buflen);
++		    if (newp == NULL)
++		      {
++			if (__builtin_expect (malloc_pwtmpbuf, 0))
++			  free (pwtmpbuf);
++			goto nomem_getpw;
++		      }
++		    pwtmpbuf = newp;
++		    malloc_pwtmpbuf = 1;
++		  }
+ 		__set_errno (save);
+ 	      }
+ #  else
+ 	    p = getpwnam (user_name);
+ #  endif
++
++	    if (__builtin_expect (malloc_user_name, 0))
++	      free (user_name);
++
++	    /* If we found a home directory use this.  */
+ 	    if (p != NULL)
+-	      home_dir = p->pw_dir;
++	      {
++		size_t home_len = strlen (p->pw_dir);
++		size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
++
++		if (__builtin_expect (malloc_dirname, 0))
++		  free (dirname);
++		malloc_dirname = 0;
++
++		if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
++		  dirname = alloca_account (home_len + rest_len + 1,
++					    alloca_used);
++		else
++		  {
++		    dirname = malloc (home_len + rest_len + 1);
++		    if (dirname == NULL)
++		      {
++			if (__builtin_expect (malloc_pwtmpbuf, 0))
++			  free (pwtmpbuf);
++			retval = GLOB_NOSPACE;
++			goto out;
++		      }
++		    malloc_dirname = 1;
++		  }
++		*((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
++				    end_name, rest_len)) = '\0';
++
++		dirlen = home_len + rest_len;
++		dirname_modified = 1;
++
++		if (__builtin_expect (malloc_pwtmpbuf, 0))
++		  free (pwtmpbuf);
++	      }
+ 	    else
+-	      home_dir = NULL;
++	      {
++		if (__builtin_expect (malloc_pwtmpbuf, 0))
++		  free (pwtmpbuf);
++
++		if (flags & GLOB_TILDE_CHECK)
++		  /* We have to regard it as an error if we cannot find the
++		     home directory.  */
++		  return GLOB_NOMATCH;
++	      }
+ 	  }
+-	  /* If we found a home directory use this.  */
+-	  if (home_dir != NULL)
+-	    {
+-	      char *newp;
+-	      size_t home_len = strlen (home_dir);
+-	      size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+-	      newp = (char *) __alloca (home_len + rest_len + 1);
+-	      *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
+-				  end_name, rest_len)) = '\0';
+-	      dirname = newp;
+-	      dirlen = home_len + rest_len;
+-	      dirname_modified = 1;
+-	    }
+-	  else
+-	    if (flags & GLOB_TILDE_CHECK)
+-	      /* We have to regard it as an error if we cannot find the
+-		 home directory.  */
+-	      return GLOB_NOMATCH;
+ 	}
+ # endif	/* Not Amiga && not WINDOWS32.  */
+     }
+@@ -899,7 +1066,7 @@ glob (pattern, flags, errfunc, pglob)
+ 	  status = glob_in_dir (filename, dirs.gl_pathv[i],
+ 				((flags | GLOB_APPEND)
+ 				 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
+-				errfunc, pglob);
++				errfunc, pglob, alloca_used);
+ 	  if (status == GLOB_NOMATCH)
+ 	    /* No matches in this directory.  Try the next.  */
+ 	    continue;
+@@ -1000,7 +1167,8 @@ glob (pattern, flags, errfunc, pglob)
+ 	}
+       if (dirname_modified)
+ 	flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
+-      status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
++      status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
++			    alloca_used);
+       if (status != 0)
+ 	{
+ 	  if (status == GLOB_NOMATCH && flags != orig_flags
+@@ -1063,7 +1231,11 @@ glob (pattern, flags, errfunc, pglob)
+ 	     sizeof (char *), collated_compare);
+     }
+ 
+-  return 0;
++ out:
++  if (__builtin_expect (malloc_dirname, 0))
++    free (dirname);
++
++  return retval;
+ }
+ #if defined _LIBC && !defined glob
+ libc_hidden_def (glob)
+@@ -1273,7 +1445,7 @@ link_exists2_p (const char *dir, size_t dirlen, const char *fname,
+ static int
+ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 	     int (*errfunc) (const char *, int),
+-	     glob_t *pglob)
++	     glob_t *pglob, size_t alloca_used)
+ {
+   size_t dirlen = strlen (directory);
+   void *stream = NULL;
+@@ -1288,11 +1460,12 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+   struct globnames *names = &init_names;
+   struct globnames *names_alloca = &init_names;
+   size_t nfound = 0;
+-  size_t allocasize = sizeof (init_names);
+   size_t cur = 0;
+   int meta;
+   int save;
+ 
++  alloca_used += sizeof (init_names);
++
+   init_names.next = NULL;
+   init_names.count = INITIAL_COUNT;
+ 
+@@ -1308,20 +1481,36 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+     {
+       /* Since we use the normal file functions we can also use stat()
+ 	 to verify the file is there.  */
+-      struct stat st;
+-      struct_stat64 st64;
++      union
++      {
++	struct stat st;
++	struct_stat64 st64;
++      } ust;
+       size_t patlen = strlen (pattern);
+-      char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
++      int alloca_fullname = __libc_use_alloca (alloca_used
++					       + dirlen + 1 + patlen + 1);
++      char *fullname;
++      if (alloca_fullname)
++	fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
++      else
++	{
++	  fullname = malloc (dirlen + 1 + patlen + 1);
++	  if (fullname == NULL)
++	    return GLOB_NOSPACE;
++	}
+ 
+       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
+ 			"/", 1),
+ 	       pattern, patlen + 1);
+       if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+-	   ? (*pglob->gl_stat) (fullname, &st)
+-	   : __stat64 (fullname, &st64)) == 0)
++	   ? (*pglob->gl_stat) (fullname, &ust.st)
++	   : __stat64 (fullname, &ust.st64)) == 0)
+ 	/* We found this file to be existing.  Now tell the rest
+ 	   of the function to copy this name into the result.  */
+ 	flags |= GLOB_NOCHECK;
++
++      if (__builtin_expect (!alloca_fullname, 0))
++	free (fullname);
+     }
+   else
+     {
+@@ -1409,9 +1598,9 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 			  size_t size = (sizeof (struct globnames)
+ 					 + ((count - INITIAL_COUNT)
+ 					    * sizeof (char *)));
+-			  allocasize += size;
+-			  if (__libc_use_alloca (allocasize))
+-			    newnames = names_alloca = __alloca (size);
++			  if (__libc_use_alloca (alloca_used + size))
++			    newnames = names_alloca
++			      = alloca_account (size, alloca_used);
+ 			  else if ((newnames = malloc (size))
+ 				   == NULL)
+ 			    goto memory_error;
--- eglibc-2.13.orig/debian/patches/any/cvs-resolv-reuse-fd.diff
+++ eglibc-2.13/debian/patches/any/cvs-resolv-reuse-fd.diff
@@ -0,0 +1,16 @@
+2014-06-03  Andreas Schwab  <schwab@suse.de>
+
+	[BZ #15946]
+	* resolv/res_send.c (send_dg): Reload file descriptor after
+	calling reopen.
+
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -1410,6 +1410,7 @@ send_dg(res_state statp,
+ 					retval = reopen (statp, terrno, ns);
+ 					if (retval <= 0)
+ 						return retval;
++					pfd[0].fd = EXT(statp).nssocks[ns];
+ 				}
+ 			}
+ 			goto wait;

-- System Information:
Debian Release: jessie/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.14-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash


Reply to: