about summary refs log tree commit diff
path: root/sysdeps/unix
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/libc_fatal.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/sysdeps/unix/sysv/linux/libc_fatal.c b/sysdeps/unix/sysv/linux/libc_fatal.c
index 7287f4ef6c..e1b4c8d314 100644
--- a/sysdeps/unix/sysv/linux/libc_fatal.c
+++ b/sysdeps/unix/sysv/linux/libc_fatal.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993-1995,1997,2000,2002-2005,2009
+/* Copyright (C) 1993-1995,1997,2000,2002-2005,2009,2011
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -20,6 +20,7 @@
 #include <atomic.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <ldsodefs.h>
 #include <paths.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -28,6 +29,7 @@
 #include <string.h>
 #include <sysdep.h>
 #include <unistd.h>
+#include <sys/mman.h>
 #include <sys/syslog.h>
 #include <execinfo.h>
 
@@ -134,18 +136,28 @@ __libc_message (int do_abort, const char *fmt, ...)
       if (cnt == total)
 	written = true;
 
-      char *buf = do_abort ? malloc (total + 1) : NULL;
-      if (buf != NULL)
+      if (do_abort)
 	{
-	  char *wp = buf;
-	  for (int cnt = 0; cnt < nlist; ++cnt)
-	    wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
-	  *wp = '\0';
-
-	  /* We have to free the old buffer since the application might
-	     catch the SIGABRT signal.  */
-	  char *old = atomic_exchange_acq (&__abort_msg, buf);
-	  free (old);
+	  total = ((total + 1 + GLRO(dl_pagesize) - 1)
+		   & ~(GLRO(dl_pagesize) - 1));
+	  struct abort_msg_s *buf = __mmap (NULL, total,
+					    PROT_READ | PROT_WRITE,
+					    MAP_ANON | MAP_PRIVATE, -1, 0);
+	  if (__builtin_expect (buf != MAP_FAILED, 1))
+	    {
+	      buf->size = total;
+	      char *wp = buf->msg;
+	      for (int cnt = 0; cnt < nlist; ++cnt)
+		wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
+	      *wp = '\0';
+
+	      /* We have to free the old buffer since the application might
+		 catch the SIGABRT signal.  */
+	      struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg,
+							     buf);
+	      if (old != NULL)
+		__munmap (old, old->size);
+	    }
 	}
     }