]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix stack overflow due to large AF_INET6 requests
authorSiddhesh Poyarekar <siddhesh@redhat.com>
Fri, 25 Oct 2013 04:52:12 +0000 (10:22 +0530)
committerAdhemerval Zanella <azanella@linux.vnet.ibm.com>
Thu, 15 Jan 2015 19:28:16 +0000 (14:28 -0500)
Resolves #16072 (CVE-2013-4458).

This patch fixes another stack overflow in getaddrinfo when it is
called with AF_INET6.  The AF_UNSPEC case was fixed as CVE-2013-1914,
but the AF_INET6 case went undetected back then.

ChangeLog
NEWS
sysdeps/posix/getaddrinfo.c

index 98203d064bc4d63f411559052e958dadaafaa447..f68d42e27d3c5994452b760f1c4ad189f2f66207 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-10-25  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+       [BZ #16072]
+       * sysdeps/posix/getaddrinfo.c (gethosts): Allocate tmpbuf on
+       heap for large requests.
+
 2013-02-12  Andreas Schwab  <schwab@suse.de>
 
        [BZ #15078]
diff --git a/NEWS b/NEWS
index 5d8a855c9932087173439547ac1b75d01034b776..5aa982b6778004f9d070882111de5827ab408d5b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,10 @@ Version 2.16.1
 * The following bugs are resolved with this release:
 
   6530, 14195, 14459, 14476, 14562, 14621, 14648, 14756, 14831, 15078.,
-  15755.
+  15755, 16072.
+
+* CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
+  for AF_INET6 has been fixed (Bugzilla #16072).
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
index 2eca2ae0e406474191a03634897e2ec0a11a598a..0146eb95b9830678c379411cba33bb9312133fb6 100644 (file)
@@ -196,7 +196,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
                                &rc, &herrno, NULL, &localcanon));            \
     if (rc != ERANGE || herrno != NETDB_INTERNAL)                            \
       break;                                                                 \
-    tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);               \
+    if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen))    \
+      tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen,              \
+                                     alloca_used);                           \
+    else                                                                     \
+      {                                                                              \
+       char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,                  \
+                             2 * tmpbuflen);                                 \
+       if (newp == NULL)                                                     \
+         {                                                                   \
+           result = -EAI_MEMORY;                                             \
+           goto free_and_return;                                             \
+         }                                                                   \
+       tmpbuf = newp;                                                        \
+       malloc_tmpbuf = true;                                                 \
+       tmpbuflen = 2 * tmpbuflen;                                            \
+      }                                                                              \
   }                                                                          \
   if (status == NSS_STATUS_SUCCESS && rc == 0)                               \
     h = &th;                                                                 \
@@ -208,7 +223,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
        {                                                                     \
          __set_h_errno (herrno);                                             \
          _res.options |= old_res_options & RES_USE_INET6;                    \
-         return -EAI_SYSTEM;                                                 \
+         result = -EAI_SYSTEM;                                               \
+         goto free_and_return;                                               \
        }                                                                     \
       if (herrno == TRY_AGAIN)                                               \
        no_data = EAI_AGAIN;                                                  \