2e9afc
commit 7cbcdb3699584db8913ca90f705d6337633ee10f
2e9afc
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
2e9afc
Date:   Fri Oct 25 10:22:12 2013 +0530
2e9afc
2e9afc
    Fix stack overflow due to large AF_INET6 requests
2e9afc
    
2e9afc
    Resolves #16072 (CVE-2013-4458).
2e9afc
    
2e9afc
    This patch fixes another stack overflow in getaddrinfo when it is
2e9afc
    called with AF_INET6.  The AF_UNSPEC case was fixed as CVE-2013-1914,
2e9afc
    but the AF_INET6 case went undetected back then.
2e9afc
12745e
diff --git glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c
2e9afc
index e6ce4cf..8ff74b4 100644
12745e
--- glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c
12745e
+++ glibc-2.17-c758a686/sysdeps/posix/getaddrinfo.c
2e9afc
@@ -197,7 +197,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
2e9afc
 				&rc, &herrno, NULL, &localcanon));	      \
2e9afc
     if (rc != ERANGE || herrno != NETDB_INTERNAL)			      \
2e9afc
       break;								      \
2e9afc
-    tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);		      \
2e9afc
+    if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen))    \
2e9afc
+      tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen,	      \
2e9afc
+				      alloca_used);			      \
2e9afc
+    else								      \
2e9afc
+      {									      \
2e9afc
+	char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,		      \
2e9afc
+			      2 * tmpbuflen);				      \
2e9afc
+	if (newp == NULL)						      \
2e9afc
+	  {								      \
2e9afc
+	    result = -EAI_MEMORY;					      \
2e9afc
+	    goto free_and_return;					      \
2e9afc
+	  }								      \
2e9afc
+	tmpbuf = newp;							      \
2e9afc
+	malloc_tmpbuf = true;						      \
2e9afc
+	tmpbuflen = 2 * tmpbuflen;					      \
2e9afc
+      }									      \
2e9afc
   }									      \
2e9afc
   if (status == NSS_STATUS_SUCCESS && rc == 0)				      \
2e9afc
     h = &th;								      \
2e9afc
@@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
2e9afc
 	{								      \
2e9afc
 	  __set_h_errno (herrno);					      \
2e9afc
 	  _res.options |= old_res_options & RES_USE_INET6;		      \
2e9afc
-	  return -EAI_SYSTEM;						      \
2e9afc
+	  result = -EAI_SYSTEM;						      \
2e9afc
+	  goto free_and_return;						      \
2e9afc
 	}								      \
2e9afc
       if (herrno == TRY_AGAIN)						      \
2e9afc
 	no_data = EAI_AGAIN;						      \