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 v2 1/3] Fix __check_pf()/make_request() stack overflow segfault (convert to malloc)


On Thu, Oct 31, 2013 at 09:10:11PM -0400, Debabrata Banerjee wrote:
> Tested calls to getaddrinfo() with 64k+ local IPv4 and IPv6 addresses.
> 
> Changelog:
> 
> 2013-10-31  Debabrata Banerjee  <dbanerje@akamai.com>
> 

As that patch was quite large and there is not much time if we want this
in 2.19 we should use a simpler patch. I wrote new patch that uses
malloc instead.

 	[BZ #16002]
 	* sysdeps/unix/sysv/linux/check_pf.c (make_request): Use malloc for
	allocations.
 
diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c
index dd333b4..e9510cb 100644
--- a/sysdeps/unix/sysv/linux/check_pf.c
+++ b/sysdeps/unix/sysv/linux/check_pf.c
@@ -102,6 +102,11 @@ cache_valid_p (void)
   return false;
 }
 
+struct freeable_data
+{
+  struct freeable_data *next;
+  char data[];
+};
 
 static struct cached_data *
 make_request (int fd, pid_t pid)
@@ -116,6 +121,7 @@ make_request (int fd, pid_t pid)
     char pad[3];
   } req;
   struct sockaddr_nl nladdr;
+  struct cached_data *result;
 
   req.nlh.nlmsg_len = sizeof (req);
   req.nlh.nlmsg_type = RTM_GETADDR;
@@ -137,19 +143,16 @@ make_request (int fd, pid_t pid)
 #else
   const size_t buf_size = __getpagesize ();
 #endif
-  bool use_malloc = false;
   char *buf;
 
-  if (__libc_use_alloca (buf_size))
-    buf = alloca (buf_size);
-  else
-    {
-      buf = malloc (buf_size);
-      if (buf != NULL)
-	use_malloc = true;
-      else
-	goto out_fail;
-    }
+  /* A linked list of allocations that we need to free at exit from function.  */
+
+  struct freeable_data *freeable_data_root = NULL;
+  struct freeable_data *freeable_data_next = NULL;
+
+  buf = malloc (buf_size);
+  if (buf == NULL)
+    goto out_fail;
 
   struct iovec iov = { buf, buf_size };
 
@@ -239,7 +242,13 @@ make_request (int fd, pid_t pid)
 		    }
 		}
 
-	      struct in6ailist *newp = alloca (sizeof (*newp));
+             freeable_data_next = malloc (sizeof (struct freeable_data)
+			         + sizeof (struct in6ailist));
+
+             freeable_data_next->next = freeable_data_root;
+             freeable_data_root = freeable_data_next;
+	      struct in6ailist *newp = (struct in6ailist *) freeable_data_next->data;
+
 	      newp->info.flags = (((ifam->ifa_flags
 				    & (IFA_F_DEPRECATED
 				       | IFA_F_OPTIMISTIC))
@@ -269,7 +278,6 @@ make_request (int fd, pid_t pid)
     }
   while (! done);
 
-  struct cached_data *result;
   if (seen_ipv6 && in6ailist != NULL)
     {
       result = malloc (sizeof (*result)
@@ -298,14 +306,21 @@ make_request (int fd, pid_t pid)
       result = &noai6ai_cached;
     }
 
-  if (use_malloc)
-    free (buf);
-  return result;
 
+fail_cnt:
+
+  while (freeable_data_root)
+    {
+      freeable_data_next = freeable_data_root->next;
+      free (freeable_data_root);
+      freeable_data_root = freeable_data_next;
+    }
+
+  free (buf);
+  return result;
 out_fail:
-  if (use_malloc)
-    free (buf);
-  return NULL;
+  result = NULL;
+  goto fail_cnt;
 }
 
 


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