]> 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)
committerWilco Dijkstra <wdijkstr@arm.com>
Thu, 19 Oct 2017 17:19:55 +0000 (18:19 +0100)
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.

ChangeLog
malloc/malloc.c

index ea655fc1021f94e8a1a5dd76be57b3f537fa712d..17a2833e59c4d9ec1e4f66e9608bfe7eb60e701b 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-10-19  Valery Reznic <valery_reznic@yahoo.com>
            H.J. Lu  <hongjiu.lu@intel.com>
 
index 6b789685ad842ca4a1de6564d691ee4d13d399fa..3d7c23917cc37c320d6618c0f9daf528da1bcda1 100644 (file)
@@ -4135,17 +4135,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);