]> 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)
committerMike Frysinger <vapier@gentoo.org>
Mon, 6 Jan 2014 13:41:15 +0000 (08:41 -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.

(cherry picked from commit 6f95434fd488e9b72117f9b93ec2e2dbf397a4d3)

sysdeps/posix/getaddrinfo.c

index 7bb3ded9af07ae2392633876c7009de2789bd3b6..2e97255133659a9b74ec1b759ace0a55912363bb 100644 (file)
@@ -197,7 +197,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;                                                                 \
@@ -209,7 +224,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;                                                  \