From patchwork Fri Nov 6 16:54:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 541040 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 42FA31402D9 for ; Sat, 7 Nov 2015 03:54:47 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b=vM+d7i0E; 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:to:from:subject:message-id:date:mime-version :content-type; q=dns; s=default; b=pEJiGFfBE2tH4LzCi0SzwOz3LIsMB Sq2gGUR9g3QiYg2xQV344/UssQdmj+Kim+MVQ12KV4HFZXdK97Bhb60ImYahvG5t R7gYruhFnd+sLU2F6mW6T0IG/4+9znpJk0k/JRXndPSBK7bz7zE5ofl/KS0Y0Nz4 WALx0iSovT1F+s= 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:to:from:subject:message-id:date:mime-version :content-type; s=default; bh=HQ+3lEyC25IZsy4X1KUTVBKHUWk=; b=vM+ d7i0ECg/Rzdk17Xv+wEQZttrin7tTAFeqYM+6azruYtUP5f7urjR+W25IMss+FMw 1FQPl4Bu+Hprb023/c+uQZyT8eiCH6ymol3xeZjWSPQfntxQfslGqNA0vrIoYdEs S1Lrm4Wv1+7/S0CssJnEnkqm3vO7v9ELDavOE0qg= Received: (qmail 34152 invoked by alias); 6 Nov 2015 16:54:41 -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 34115 invoked by uid 89); 6 Nov 2015 16:54:40 -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 To: GNU C Library From: Florian Weimer Subject: [PATCH] malloc: Do not free or realloc chunks in corrupt arenas X-Enigmail-Draft-Status: N1110 Message-ID: <563CDB4C.1010806@redhat.com> Date: Fri, 6 Nov 2015 17:54:36 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 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 * 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);