From patchwork Fri Nov 6 16:57:51 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 541041 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 034991402D7 for ; Sat, 7 Nov 2015 03:58:01 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b=FhGyaZvg; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:subject:to:references:from:message-id:date :mime-version:in-reply-to:content-type; q=dns; s=default; b=bMNp YHkaBi+z1TvvIk5L3/30A832ejiKdkH9DaCSOh/olakm0WAHDmmvXRKuX2tm5RaE rh8FlZmdqgO/RhBbYb4bGCJgVqAkFi3acZacXzaIRY07OSq/CUtfQJKyCIR4mQkv AFAxOv3mETq47D269uCBjX0NxDgPqQ2vChsEVOk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:subject:to:references:from:message-id:date :mime-version:in-reply-to:content-type; s=default; bh=x62SDZeptX ttYbJsZHbsk5Wk9Q8=; b=FhGyaZvgb5P6NuZigv9cjYVRoPWkaUUtzhJ/ic7H7N iUUUBvbksSFI94s4CuRCC+Ar5pTtDQVrI5vQrX8XdlHZNMxURnlnzLmx+lvfA3nq rNaNyEYHkITB9vFOtdVDUn5Gjceii8Z9fBMwITCTIAFBu2cZASb0Q+cjNKDgAKKd 8= Received: (qmail 38596 invoked by alias); 6 Nov 2015 16:57:56 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 38581 invoked by uid 89); 6 Nov 2015 16:57:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Subject: [PATCH v1a] malloc: Do not free or realloc chunks in corrupt arenas To: GNU C Library References: <563CDB4C.1010806@redhat.com> From: Florian Weimer Message-ID: <563CDC0F.3090105@redhat.com> Date: Fri, 6 Nov 2015 17:57:51 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 In-Reply-To: <563CDB4C.1010806@redhat.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 * 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);