aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/futex.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-03-14 05:34:35 -0400
committerThomas Gleixner <tglx@linutronix.de>2011-03-14 16:08:47 -0400
commit6e0aa9f8a8190e0879a29bd67aa606b51734a122 (patch)
tree66b92176051147b87031cc2755639c39f8a900f8 /kernel/futex.c
parent995612178c88407d8330f580ba6572cb8b284dd8 (diff)
futex: Deobfuscate handle_futex_death()
handle_futex_death() uses futex_atomic_cmpxchg_inatomic() without disabling page faults. That's ok, but totally non obvious. We don't hold locks so we actually can and want to fault here, because the get_user() before futex_atomic_cmpxchg_inatomic() does not guarantee a R/W mapping. We could just add a big fat comment to explain this, but actually changing the code so that the functionality is entirely clear is better. Use the helper function which disables page faults around the futex_atomic_cmpxchg_inatomic() and handle a fault with a call to fault_in_user_writeable() as all other places in the futex code do as well. Pointed-out-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Darren Hart <darren@dvhart.com> Cc: Michel Lespinasse <walken@google.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Matt Turner <mattst88@gmail.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: David Howells <dhowells@redhat.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Michal Simek <monstr@monstr.eu> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: "James E.J. Bottomley" <jejb@parisc-linux.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Paul Mundt <lethal@linux-sh.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Chris Metcalf <cmetcalf@tilera.com> LKML-Reference: <alpine.LFD.2.00.1103141126590.2787@localhost6.localdomain6> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/futex.c')
-rw-r--r--kernel/futex.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index c6bef6e404fe..e9251d934f7d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -2458,9 +2458,20 @@ retry:
2458 * userspace. 2458 * userspace.
2459 */ 2459 */
2460 mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; 2460 mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
2461 if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval)) 2461 /*
2462 return -1; 2462 * We are not holding a lock here, but we want to have
2463 2463 * the pagefault_disable/enable() protection because
2464 * we want to handle the fault gracefully. If the
2465 * access fails we try to fault in the futex with R/W
2466 * verification via get_user_pages. get_user() above
2467 * does not guarantee R/W access. If that fails we
2468 * give up and leave the futex locked.
2469 */
2470 if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) {
2471 if (fault_in_user_writeable(uaddr))
2472 return -1;
2473 goto retry;
2474 }
2464 if (nval != uval) 2475 if (nval != uval)
2465 goto retry; 2476 goto retry;
2466 2477