This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v1a] 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:57:51 +0100
- Subject: [PATCH v1a] malloc: Do not free or realloc chunks in corrupt arenas
- Authentication-results: sourceware.org; auth=none
- References: <563CDB4C dot 1010806 at redhat dot com>
On 11/06/2015 05:54 PM, Florian Weimer wrote:
> 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.
Sorry, wrong version of patch attached. This is the correct one, I hope.
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..2446c4a 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 *newmem = __libc_malloc (bytes);
+ if (__glibc_unlikely (newmem == NULL))
+ return NULL;
+ memcpy (newmem, oldmem, oldsize);
+
+ /* Do not free the old object because the arena is known to be
+ corrupt. */
+ return newmem;
+}
+
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);