This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] malloc: Do not free or realloc chunks in corrupt arenas
- From: Florian Weimer <fweimer at redhat dot com>
- To: GNU C Library <libc-alpha at sourceware dot org>
- Date: Fri, 6 Nov 2015 17:54:36 +0100
- Subject: [PATCH] malloc: Do not free or realloc chunks in corrupt arenas
- Authentication-results: sourceware.org; auth=none
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);