about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSiddhesh Poyarekar <siddhesh@redhat.com>2013-10-25 10:22:12 +0530
committerAllan McRae <allan@archlinux.org>2013-10-25 23:59:00 +1000
commit0b0e50ce9efe2fec10e147eddba4f0802235a042 (patch)
treefee0b57716e3c388721f61b73059fbd5f96dbb28
parent54377921e7092f709c6a5985688769404637055f (diff)
downloadglibc-archlinux/2.18/master.tar.gz
glibc-archlinux/2.18/master.tar.xz
glibc-archlinux/2.18/master.zip
Fix stack overflow due to large AF_INET6 requests archlinux/2.18/master
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 7cbcdb3699584db8913ca90f705d6337633ee10f)

Conflicts:
	NEWS
-rw-r--r--ChangeLog6
-rw-r--r--sysdeps/posix/getaddrinfo.c20
2 files changed, 24 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 3b61bc8ce7..1bb856896b 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/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 8a27f0ddb7..09aeb38e6b 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;						      \