]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix race in corruption check.
authorUlrich Drepper <drepper@redhat.com>
Thu, 16 Jul 2009 16:54:34 +0000 (09:54 -0700)
committerPetr Baudis <pasky@suse.cz>
Thu, 16 Jul 2009 18:36:06 +0000 (20:36 +0200)
With atomic fastbins the checks performed can race with concurrent
modifications of the arena.  If we detect a problem re-do the test
after getting the lock.
(cherry picked from commit bec466d922ee22b94ac0d00415fb605e136efe6e)

ChangeLog
malloc/malloc.c

index 8a0e7ab6d1f48912809517e07aea46dc7b61e19c..34a5ad631c996b7a0e0748fe955c7aa0989730dc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-07-16  Ulrich Drepper  <drepper@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       * malloc/malloc.c [ATOMIC_FASTBINS] (_int_free): Make check for
+       corruption thread-safe.
+
 2009-07-13  Jakub Jelinek  <jakub@redhat.com>
 
        * include/atomic.h (catomic_compare_and_exchange_val_rel): If arch
index bd44dee7f418f28602de3748dd9a6e73f5d8b33d..4b623e2200ced27dd0beab19e9444d398f14aa3b 100644 (file)
@@ -4779,8 +4779,29 @@ _int_free(mstate av, mchunkptr p)
        || __builtin_expect (chunksize (chunk_at_offset (p, size))
                             >= av->system_mem, 0))
       {
-       errstr = "free(): invalid next size (fast)";
-       goto errout;
+#ifdef ATOMIC_FASTBINS
+       /* 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
+           || ({ assert (locked == 0);
+                 mutex_lock(&av->mutex);
+                 locked = 1;
+                 chunk_at_offset (p, size)->size <= 2 * SIZE_SZ
+                   || chunksize (chunk_at_offset (p, size)) >= av->system_mem;
+             }))
+#endif
+         {
+           errstr = "free(): invalid next size (fast)";
+           goto errout;
+         }
+#ifdef ATOMIC_FASTBINS
+       if (! have_lock)
+         {
+           (void)mutex_unlock(&av->mutex);
+           locked = 0;
+         }
+#endif
       }
 
     if (__builtin_expect (perturb_byte, 0))