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] malloc: Do not free or realloc chunks in corrupt arenas


I am not sure if this is an actual bug in the malloc backtrace patch, or
if this is can only happen once there are additional sources of corrupt
arenas besides the malloc backtrace path

This was found through code inspection.  I do not have a test case at
the moment.

Florian
2015-11-06  Florian Weimer  <fweimer@redhat.com>

	* malloc/malloc.c (__libc_free): Do not free chunks in corrupt
	arenas.
	(realloc_from_corrupt): New function.
	(__libc_realloc): Call it for corrupt arenas.

diff --git a/malloc/malloc.c b/malloc/malloc.c
index 839263e..bce94da 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2966,10 +2966,38 @@ __libc_free (void *mem)
     }
 
   ar_ptr = arena_for_chunk (p);
+
+  if (__glibc_unlikely (arena_is_corrupt (ar_ptr)))
+    /* Do nothing if the arena is known to be corrupt.  */
+    return;
+
   _int_free (ar_ptr, p, 0);
 }
 libc_hidden_def (__libc_free)
 
+/* Always make a copy to enlarge a chunk in a corrupt arena.  The
+   chunk must not have been allocated with mmap.  */
+static void *
+realloc_from_corrupt (void *oldmem, size_t bytes,
+		      INTERNAL_SIZE_T oldsize)
+{
+  /* Size adjustment for the non-mmap case.  */
+  oldsize -= SIZE_SZ;
+
+  /* Reuse the old chunk if possible.  */
+  if (oldsize >= bytes)
+    return oldmem;
+
+  void *new_mem = __libc_malloc (bytes);
+  if (__glibc_unlikely (new_mem == NULL))
+    return NULL;
+  memcpy (new_mem, old_mem, oldsize);
+
+  /* Do not free the old object because the arena is known to be
+     corrupt.  */
+  return new_mem;
+}
+
 void *
 __libc_realloc (void *oldmem, size_t bytes)
 {
@@ -3041,6 +3069,9 @@ __libc_realloc (void *oldmem, size_t bytes)
       return newmem;
     }
 
+  if (__glibc_unlikely (arena_is_corrupt (ar_ptr)))
+    return realloc_from_corrupt (oldmem, bytes, oldsize);
+
   (void) mutex_lock (&ar_ptr->mutex);
 
   newp = _int_realloc (ar_ptr, oldp, oldsize, nb);

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