summary refs log tree commit diff
diff options
context:
space:
mode:
authorSiddhesh Poyarekar <siddhesh@redhat.com>2013-10-25 10:22:12 +0530
committerSiddhesh Poyarekar <siddhesh@redhat.com>2013-10-25 10:22:12 +0530
commit7cbcdb3699584db8913ca90f705d6337633ee10f (patch)
treea260a3b6afb62ce20602c0672b6ea040e4db2c8c
parent894f3f1049135dcbeaab8f18690973663ef3147c (diff)
downloadglibc-7cbcdb3699584db8913ca90f705d6337633ee10f.tar.gz
glibc-7cbcdb3699584db8913ca90f705d6337633ee10f.tar.xz
glibc-7cbcdb3699584db8913ca90f705d6337633ee10f.zip
Fix stack overflow due to large AF_INET6 requests
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.
-rw-r--r--ChangeLog6
-rw-r--r--NEWS5
-rw-r--r--sysdeps/posix/getaddrinfo.c20
3 files changed, 28 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 85cc5da1b2..05a8f05db0 100644
--- 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-10-25  Aurelien Jarno  <aurelien@aurel32.net>
 
 	[BZ #9954]
diff --git a/NEWS b/NEWS
index 3358ac6c84..9199b90d13 100644
--- a/NEWS
+++ b/NEWS
@@ -15,7 +15,7 @@ Version 2.19
   15734, 15735, 15736, 15748, 15749, 15754, 15760, 15764, 15797, 15825,
   15844, 15847, 15849, 15855, 15856, 15857, 15859, 15867, 15886, 15887,
   15890, 15892, 15893, 15895, 15897, 15905, 15909, 15919, 15921, 15923,
-  15939, 15948, 15963, 15966, 15988, 16032, 16034, 16036, 16041.
+  15939, 15948, 15963, 15966, 15988, 16032, 16034, 16036, 16041, 16072.
 
 * CVE-2012-4412 The strcoll implementation caches indices and rules for
   large collation sequences to optimize multiple passes.  This cache
@@ -44,6 +44,9 @@ Version 2.19
   heap when passed very large allocation size values (Bugzilla #15855,
   #15856, #15857).
 
+* CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
+  for AF_INET6 has been fixed (Bugzilla #16072).
+
 * New locales: ak_GH, cmn_TW, hak_TW, lzh_TW, nan_TW, quz_PE, pap_AW, pap_CW,
   ar_SS.
 
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index e6ce4cfd63..8ff74b4965 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -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;						      \