aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include
diff options
context:
space:
mode:
authorMichel Lespinasse <walken@google.com>2011-03-10 21:48:51 -0500
committerThomas Gleixner <tglx@linutronix.de>2011-03-11 06:23:08 -0500
commit37a9d912b24f96a0591773e6e6c3642991ae5a70 (patch)
tree5c4d5b9a52e2c533269e589115afbd25b6c8534b /arch/arm/include
parent522d7decc0370070448a8c28982c8dfd8970489e (diff)
futex: Sanitize cmpxchg_futex_value_locked API
The cmpxchg_futex_value_locked API was funny in that it returned either the original, user-exposed futex value OR an error code such as -EFAULT. This was confusing at best, and could be a source of livelocks in places that retry the cmpxchg_futex_value_locked after trying to fix the issue by running fault_in_user_writeable(). This change makes the cmpxchg_futex_value_locked API more similar to the get_futex_value_locked one, returning an error code and updating the original value through a reference argument. Signed-off-by: Michel Lespinasse <walken@google.com> Acked-by: Chris Metcalf <cmetcalf@tilera.com> [tile] Acked-by: Tony Luck <tony.luck@intel.com> [ia64] Acked-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Michal Simek <monstr@monstr.eu> [microblaze] Acked-by: David Howells <dhowells@redhat.com> [frv] Cc: Darren Hart <darren@dvhart.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Matt Turner <mattst88@gmail.com> Cc: Russell King <linux@arm.linux.org.uk> 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: Linus Torvalds <torvalds@linux-foundation.org> LKML-Reference: <20110311024851.GC26122@google.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/arm/include')
-rw-r--r--arch/arm/include/asm/futex.h18
1 files changed, 10 insertions, 8 deletions
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 7133a8620830..d20b78fce758 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -88,9 +88,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
88} 88}
89 89
90static inline int 90static inline int
91futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 91futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
92 int oldval, int newval)
92{ 93{
93 int val; 94 int ret = 0, val;
94 95
95 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 96 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
96 return -EFAULT; 97 return -EFAULT;
@@ -99,24 +100,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
99 * call sites. */ 100 * call sites. */
100 101
101 __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" 102 __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
102 "1: " T(ldr) " %0, [%3]\n" 103 "1: " T(ldr) " %1, [%4]\n"
103 " teq %0, %1\n" 104 " teq %1, %2\n"
104 " it eq @ explicit IT needed for the 2b label\n" 105 " it eq @ explicit IT needed for the 2b label\n"
105 "2: " T(streq) " %2, [%3]\n" 106 "2: " T(streq) " %3, [%4]\n"
106 "3:\n" 107 "3:\n"
107 " .pushsection __ex_table,\"a\"\n" 108 " .pushsection __ex_table,\"a\"\n"
108 " .align 3\n" 109 " .align 3\n"
109 " .long 1b, 4f, 2b, 4f\n" 110 " .long 1b, 4f, 2b, 4f\n"
110 " .popsection\n" 111 " .popsection\n"
111 " .pushsection .fixup,\"ax\"\n" 112 " .pushsection .fixup,\"ax\"\n"
112 "4: mov %0, %4\n" 113 "4: mov %0, %5\n"
113 " b 3b\n" 114 " b 3b\n"
114 " .popsection" 115 " .popsection"
115 : "=&r" (val) 116 : "+r" (ret), "=&r" (val)
116 : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT) 117 : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
117 : "cc", "memory"); 118 : "cc", "memory");
118 119
119 return val; 120 *uval = val;
121 return ret;
120} 122}
121 123
122#endif /* !SMP */ 124#endif /* !SMP */