This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/3] Fix __check_pf()/make_request() stack overflow segfault (convert to alloca_account)


Tested calls to getaddrinfo() with 64k+ local IPv4 and IPv6 addresses.

Changelog:

2013-10-31  Debabrata Banerjee  <dbanerje@akamai.com>

	[BZ #16002]
	* sysdeps/unix/sysv/linux/check_pf.c (make_request): Use alloca_account
	for allocations and fallback to malloc

Signed-off-by: Debabrata Banerjee <dbanerje@akamai.com>
---
 sysdeps/unix/sysv/linux/check_pf.c | 87 ++++++++++++++++++++++++++++----------
 1 file changed, 65 insertions(+), 22 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c
index 34c2146..5dd7650 100644
--- a/sysdeps/unix/sysv/linux/check_pf.c
+++ b/sysdeps/unix/sysv/linux/check_pf.c
@@ -139,9 +139,12 @@ make_request (int fd, pid_t pid)
 #endif
   bool use_malloc = false;
   char *buf;
+  size_t alloca_used = 0;
+  size_t result_size = 0;
+  struct cached_data *result = NULL;
 
   if (__libc_use_alloca (buf_size))
-    buf = alloca (buf_size);
+    buf = alloca_account (buf_size, alloca_used);
   else
     {
       buf = malloc (buf_size);
@@ -206,6 +209,8 @@ make_request (int fd, pid_t pid)
 
 	      const void *local = NULL;
 	      const void *address = NULL;
+              struct in6addrinfo *tmp_info;
+
 	      while (RTA_OK (rta, len))
 		{
 		  switch (rta->rta_type)
@@ -239,28 +244,64 @@ make_request (int fd, pid_t pid)
 		    }
 		}
 
-	      struct in6ailist *newp = alloca (sizeof (*newp));
-	      newp->info.flags = (((ifam->ifa_flags
-				    & (IFA_F_DEPRECATED
-				       | IFA_F_OPTIMISTIC))
-				   ? in6ai_deprecated : 0)
-				  | ((ifam->ifa_flags
-				      & IFA_F_HOMEADDRESS)
-				     ? in6ai_homeaddress : 0));
-	      newp->info.prefixlen = ifam->ifa_prefixlen;
-	      newp->info.index = ifam->ifa_index;
-	      if (ifam->ifa_family == AF_INET)
-		{
-		  newp->info.addr[0] = 0;
-		  newp->info.addr[1] = 0;
-		  newp->info.addr[2] = htonl (0xffff);
-		  newp->info.addr[3] = *(const in_addr_t *) address;
-		}
+	      if (__libc_use_alloca (alloca_used + sizeof (struct in6ailist)))
+                {
+                  struct in6ailist *newp = alloca_account (sizeof (*newp), alloca_used);
+                  newp->next = in6ailist;
+                  in6ailist = newp;
+                  tmp_info = &newp->info;
+                }
 	      else
-		memcpy (newp->info.addr, address, sizeof (newp->info.addr));
-	      newp->next = in6ailist;
-	      in6ailist = newp;
-	      ++in6ailistlen;
+	        {
+	          size_t allocate_size;
+	          
+                  if (result_size < sizeof (*result)
+	              + ((in6ailistlen + 1) * sizeof (struct in6addrinfo)))
+	            {
+	              allocate_size = sizeof (*result)
+	                      + (2 * in6ailistlen * sizeof (struct in6addrinfo));
+	              void *newbuf = realloc (result, allocate_size);
+	              if (newbuf != NULL)
+	                result = newbuf;
+	              else
+	                goto out_fail;
+
+                      if (result_size == 0)
+                        {
+                          int i = 0;
+                          do
+                            {
+                              result->in6ai[i++] = in6ailist->info;
+                              in6ailist = in6ailist->next;
+                            }
+                          while (in6ailist != NULL);
+                        }
+
+                      result_size = allocate_size;
+	            }
+		  tmp_info = &result->in6ai[in6ailistlen];
+	        }
+
+              tmp_info->flags = (((ifam->ifa_flags
+                                    & (IFA_F_DEPRECATED
+                                       | IFA_F_OPTIMISTIC))
+                                   ? in6ai_deprecated : 0)
+                                  | ((ifam->ifa_flags
+                                      & IFA_F_HOMEADDRESS)
+                                     ? in6ai_homeaddress : 0));
+              tmp_info->prefixlen = ifam->ifa_prefixlen;
+              tmp_info->index = ifam->ifa_index;
+              if (ifam->ifa_family == AF_INET)
+                {
+                  tmp_info->addr[0] = 0;
+                  tmp_info->addr[1] = 0;
+                  tmp_info->addr[2] = htonl (0xffff);
+                  tmp_info->addr[3] = *(const in_addr_t *) address;
+                }
+              else
+                memcpy (tmp_info->addr, address, sizeof (tmp_info->addr));
+
+              ++in6ailistlen;
 	    }
 	  else if (nlmh->nlmsg_type == NLMSG_DONE)
 	    /* We found the end, leave the loop.  */
@@ -305,6 +346,8 @@ make_request (int fd, pid_t pid)
 out_fail:
   if (use_malloc)
     free (buf);
+  if (result)
+    free (result);
   return NULL;
 }
 
-- 
1.8.3.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]