diff options
author | Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> | 2017-01-03 17:16:02 -0200 |
---|---|---|
committer | Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> | 2017-01-03 17:21:41 -0200 |
commit | e9a96ea1aca4ebaa7c86e8b83b766f118d689d0f (patch) | |
tree | c8171c3229049caaea73c8f5ee2f2f068c02669b /sysdeps/unix/sysv/linux/powerpc/elision-trylock.c | |
parent | daaff5cc793acdd4f8667fca3b901647b4c34363 (diff) | |
download | glibc-e9a96ea1aca4ebaa7c86e8b83b766f118d689d0f.tar.gz glibc-e9a96ea1aca4ebaa7c86e8b83b766f118d689d0f.tar.xz glibc-e9a96ea1aca4ebaa7c86e8b83b766f118d689d0f.zip |
powerpc: Fix write-after-destroy in lock elision [BZ #20822]
The update of *adapt_count after the release of the lock causes a race condition when thread A unlocks, thread B continues and destroys the mutex, and thread A writes to *adapt_count.
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/elision-trylock.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/elision-trylock.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c b/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c index 1e5cbe8610..ed244d3f12 100644 --- a/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c +++ b/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c @@ -34,7 +34,7 @@ __lll_trylock_elision (int *futex, short *adapt_count) __libc_tabort (_ABORT_NESTED_TRYLOCK); /* Only try a transaction if it's worth it. */ - if (*adapt_count > 0) + if (atomic_load_relaxed (adapt_count) > 0) { goto use_lock; } @@ -49,7 +49,7 @@ __lll_trylock_elision (int *futex, short *adapt_count) __libc_tend (0); if (aconf.skip_lock_busy > 0) - *adapt_count = aconf.skip_lock_busy; + atomic_store_relaxed (adapt_count, aconf.skip_lock_busy); } else { @@ -59,7 +59,8 @@ __lll_trylock_elision (int *futex, short *adapt_count) result in another failure. Use normal locking now and for the next couple of calls. */ if (aconf.skip_trylock_internal_abort > 0) - *adapt_count = aconf.skip_trylock_internal_abort; + atomic_store_relaxed (adapt_count, + aconf.skip_trylock_internal_abort); } } |