about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@suse.de>2013-03-21 15:50:27 +0100
committerAndreas Schwab <schwab@suse.de>2013-04-03 17:39:15 +0200
commit1cef1b19089528db11f221e938f60b9b048945d7 (patch)
tree574123f937b0a706451c792b65189bbee2c1c35f
parent74d87055bfeb31ea37bc2356d88c065c612e1c0e (diff)
downloadglibc-1cef1b19089528db11f221e938f60b9b048945d7.tar.gz
glibc-1cef1b19089528db11f221e938f60b9b048945d7.tar.xz
glibc-1cef1b19089528db11f221e938f60b9b048945d7.zip
Fix stack overflow in getaddrinfo with many results
-rw-r--r--ChangeLog6
-rw-r--r--NEWS5
-rw-r--r--sysdeps/posix/getaddrinfo.c23
3 files changed, 31 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 3046d2e3ed..deebea49f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-04-03  Andreas Schwab  <schwab@suse.de>
+
+	[BZ #15330]
+	* sysdeps/posix/getaddrinfo.c (getaddrinfo): Allocate results and
+	order arrays from heap if bigger than alloca cutoff.
+
 2013-04-03  Thomas Schwinge  <thomas@codesourcery.com>
 
 	* sysdeps/i386/fpu/math-tests.h (SNAN_TESTS_float)
diff --git a/NEWS b/NEWS
index 7718a0a14d..8ecb2ee72c 100644
--- a/NEWS
+++ b/NEWS
@@ -13,7 +13,10 @@ Version 2.18
   14317, 14327, 14496, 14812, 14920, 14964, 14981, 14982, 14985, 14994,
   14996, 15003, 15006, 15020, 15023, 15036, 15054, 15055, 15062, 15078,
   15160, 15214, 15232, 15234, 15283, 15285, 15287, 15304, 15305, 15307,
-  15327.
+  15327, 15330.
+
+* CVE-2013-1914 Stack overflow in getaddrinfo with many results has been
+  fixed (Bugzilla #15330).
 
 * Add support for calling C++11 thread_local object destructors on thread
   and program exit.  This needs compiler support for offloading C++11
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index d95c2d1156..230928181c 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -2489,11 +2489,27 @@ getaddrinfo (const char *name, const char *service,
       __typeof (once) old_once = once;
       __libc_once (once, gaiconf_init);
       /* Sort results according to RFC 3484.  */
-      struct sort_result results[nresults];
-      size_t order[nresults];
+      struct sort_result *results;
+      size_t *order;
       struct addrinfo *q;
       struct addrinfo *last = NULL;
       char *canonname = NULL;
+      bool malloc_results;
+
+      malloc_results
+	= !__libc_use_alloca (nresults * (sizeof (*results) + sizeof (size_t)));
+      if (malloc_results)
+	{
+	  results = malloc (nresults * (sizeof (*results) + sizeof (size_t)));
+	  if (results == NULL)
+	    {
+	      __free_in6ai (in6ai);
+	      return EAI_MEMORY;
+	    }
+	}
+      else
+	results = alloca (nresults * (sizeof (*results) + sizeof (size_t)));
+      order = (size_t *) (results + nresults);
 
       /* Now we definitely need the interface information.  */
       if (! check_pf_called)
@@ -2664,6 +2680,9 @@ getaddrinfo (const char *name, const char *service,
 
       /* Fill in the canonical name into the new first entry.  */
       p->ai_canonname = canonname;
+
+      if (malloc_results)
+	free (results);
     }
 
   __free_in6ai (in6ai);