From patchwork Tue Nov 13 12:03:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Maris X-Patchwork-Id: 30133 Received: (qmail 39410 invoked by alias); 13 Nov 2018 12:03:32 -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 39397 invoked by uid 89); 13 Nov 2018 12:03:31 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com From: Adam Maris To: "libc-alpha@sourceware.org" Subject: [PATCH] malloc: Ensure tcache count won't overflow Date: Tue, 13 Nov 2018 13:03:27 +0100 Message-ID: <85673514.nCShmV6Tfd@amaris.nx> MIME-Version: 1.0 Fixes bug 23733. This patch replaces the assert on tcache->entries with tcache->counts in tcache_get() which was probably done by mistake. If tcache->entries were 0, it would segfault when dereferencing e anyway. This will make sure the chunks are not served from empty tcache bin in case the pointer to next chunk of last chunk in tcache gets corrupted. Includes test case. Tested with no regressions. * malloc/Makefile: Add new test. * malloc/malloc.c (tcache_get): Check if tcache count > 0. * malloc/tst-tcache-count.c: New. diff --git a/malloc/Makefile b/malloc/Makefile index 7d54bad866..508208f24b 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -38,6 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ tst-malloc_info \ tst-malloc-too-large \ tst-malloc-stats-cancellation \ + tst-malloc-tcache-count \ tests-static := \ tst-interpose-static-nothread \ diff --git a/malloc/malloc.c b/malloc/malloc.c index bfc605aa3e..0a0e8a5863 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -2930,7 +2930,7 @@ tcache_get (size_t tc_idx) { tcache_entry *e = tcache->entries[tc_idx]; assert (tc_idx < TCACHE_MAX_BINS); - assert (tcache->entries[tc_idx] > 0); + assert (tcache->counts[tc_idx] > 0); tcache->entries[tc_idx] = e->next; --(tcache->counts[tc_idx]); return (void *) e; diff --git a/malloc/tst-malloc-tcache-count.c b/malloc/tst-malloc-tcache-count.c index e69de29bb2..bd832dd7e5 100644 --- a/malloc/tst-malloc-tcache-count.c +++ b/malloc/tst-malloc-tcache-count.c @@ -0,0 +1,54 @@ +/* Ensure tcache count won't overflow, serving chunks from empty tcache bin + Copyright (C) 2015-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +// SZ - arbitrary size to fit the chunk in tcache +#define SZ 32 + +/* this is to prevent compiler from optimizing out + the test code */ +#pragma GCC optimize ("O0") + +static int +do_test (void) +{ + void* p = malloc(SZ); + void* q = malloc(SZ); + + free(p); + free(q); + + // corrupt the next pointer of last chunk in tcache + memcpy(p, &q, sizeof(void*)); + + malloc(SZ); + malloc(SZ); + malloc(SZ); + + FAIL_RET("no assertion due to tcache chunk corruption"); +} + +#pragma GCC optimize ("O3") + +#define EXPECTED_SIGNAL SIGABRT +#include