From be9548f2bef30b75294fdd0eb6721d1bf6e6a56a Mon Sep 17 00:00:00 2001 From: David Goldblatt Date: Tue, 13 Oct 2020 12:40:34 -0700 Subject: [PATCH] Tcaches: Fix a subtle race condition. Without a lock held continuously between checking tcaches_past and incrementing it, it's possible for two threads to go down manual creation path simultaneously. If the number of tcaches is one less than the maximum, it's possible for both to create a tcache and increment tcaches_past, with the second thread returning a value larger than TCACHES_MAX. --- src/tcache.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tcache.c b/src/tcache.c index b681ee10..90ca372e 100644 --- a/src/tcache.c +++ b/src/tcache.c @@ -767,7 +767,7 @@ static bool tcaches_create_prep(tsd_t *tsd, base_t *base) { bool err; - malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); + malloc_mutex_assert_owner(tsd_tsdn(tsd), &tcaches_mtx); if (tcaches == NULL) { tcaches = base_alloc(tsd_tsdn(tsd), base, @@ -785,7 +785,6 @@ tcaches_create_prep(tsd_t *tsd, base_t *base) { err = false; label_return: - malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); return err; } @@ -795,6 +794,8 @@ tcaches_create(tsd_t *tsd, base_t *base, unsigned *r_ind) { bool err; + malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); + if (tcaches_create_prep(tsd, base)) { err = true; goto label_return; @@ -807,7 +808,6 @@ tcaches_create(tsd_t *tsd, base_t *base, unsigned *r_ind) { } tcaches_t *elm; - malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); if (tcaches_avail != NULL) { elm = tcaches_avail; tcaches_avail = tcaches_avail->next; @@ -819,10 +819,10 @@ tcaches_create(tsd_t *tsd, base_t *base, unsigned *r_ind) { *r_ind = tcaches_past; tcaches_past++; } - malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); err = false; label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); witness_assert_depth(tsdn_witness_tsdp_get(tsd_tsdn(tsd)), 0); return err; }