[v1a] malloc: Do not free or realloc chunks in corrupt arenas
Commit Message
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.
@@ -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);