]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix deadlock in _int_free consistency check
authorWilco Dijkstra <wdijkstr@arm.com>
Thu, 19 Oct 2017 17:19:55 +0000 (18:19 +0100)
committerSiddhesh Poyarekar <siddhesh@sourceware.org>
Tue, 28 Nov 2017 13:43:49 +0000 (19:13 +0530)
This patch fixes a deadlock in the fastbin consistency check.
If we fail the fast check due to concurrent modifications to
the next chunk or system_mem, we should not lock if we already
have the arena lock.  Simplify the check to make it obviously
correct.

* malloc/malloc.c (_int_free): Fix deadlock bug in consistency check.

(cherry-pick d74e6f6c0de55fc588b1ac09c88eb0fb8b8600af)

ChangeLog
malloc/malloc.c

index d536c9a832c92df50a45e91cc0948e9137fad0c8..49b720fdbb433893efddaf321749270498e2a5cf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2017-10-19  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       * malloc/malloc.c (_int_free): Fix deadlock bug in consistency check.
+
 2017-08-31  Florian Weimer  <fweimer@redhat.com>
 
        * malloc/malloc.c (_int_free): Remove locked variable and related
index 3608b34b89dfa151b6a874e2bb83b4d7e1d4f781..44996e020a91555bb82702804776a028043780fe 100644 (file)
@@ -4148,17 +4148,20 @@ _int_free (mstate av, mchunkptr p, int have_lock)
        || __builtin_expect (chunksize (chunk_at_offset (p, size))
                             >= av->system_mem, 0))
       {
+       bool fail = true;
        /* We might not have a lock at this point and concurrent modifications
-          of system_mem might have let to a false positive.  Redo the test
-          after getting the lock.  */
-       if (!have_lock
-           || ({ __libc_lock_lock (av->mutex);
-                 chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ
-                 || chunksize (chunk_at_offset (p, size)) >= av->system_mem;
-               }))
+          of system_mem might result in a false positive.  Redo the test after
+          getting the lock.  */
+       if (!have_lock)
+         {
+           __libc_lock_lock (av->mutex);
+           fail = (chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ
+                   || chunksize (chunk_at_offset (p, size)) >= av->system_mem);
+           __libc_lock_unlock (av->mutex);
+         }
+
+       if (fail)
          malloc_printerr ("free(): invalid next size (fast)");
-       if (! have_lock)
-         __libc_lock_unlock (av->mutex);
       }
 
     free_perturb (chunk2mem(p), size - 2 * SIZE_SZ);