aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
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/mips
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/mips')
-rw-r--r--arch/mips/include/asm/futex.h32
1 files changed, 17 insertions, 15 deletions
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index b9cce90346cf..692a24bd83b7 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -132,9 +132,10 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
132} 132}
133 133
134static inline int 134static inline int
135futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 135futex_atomic_cmpxchg_inatomic(int *uval, int __user *uaddr,
136 int oldval, int newval)
136{ 137{
137 int retval; 138 int ret = 0, val;
138 139
139 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 140 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
140 return -EFAULT; 141 return -EFAULT;
@@ -145,25 +146,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
145 " .set push \n" 146 " .set push \n"
146 " .set noat \n" 147 " .set noat \n"
147 " .set mips3 \n" 148 " .set mips3 \n"
148 "1: ll %0, %2 \n" 149 "1: ll %1, %3 \n"
149 " bne %0, %z3, 3f \n" 150 " bne %1, %z4, 3f \n"
150 " .set mips0 \n" 151 " .set mips0 \n"
151 " move $1, %z4 \n" 152 " move $1, %z5 \n"
152 " .set mips3 \n" 153 " .set mips3 \n"
153 "2: sc $1, %1 \n" 154 "2: sc $1, %2 \n"
154 " beqzl $1, 1b \n" 155 " beqzl $1, 1b \n"
155 __WEAK_LLSC_MB 156 __WEAK_LLSC_MB
156 "3: \n" 157 "3: \n"
157 " .set pop \n" 158 " .set pop \n"
158 " .section .fixup,\"ax\" \n" 159 " .section .fixup,\"ax\" \n"
159 "4: li %0, %5 \n" 160 "4: li %0, %6 \n"
160 " j 3b \n" 161 " j 3b \n"
161 " .previous \n" 162 " .previous \n"
162 " .section __ex_table,\"a\" \n" 163 " .section __ex_table,\"a\" \n"
163 " "__UA_ADDR "\t1b, 4b \n" 164 " "__UA_ADDR "\t1b, 4b \n"
164 " "__UA_ADDR "\t2b, 4b \n" 165 " "__UA_ADDR "\t2b, 4b \n"
165 " .previous \n" 166 " .previous \n"
166 : "=&r" (retval), "=R" (*uaddr) 167 : "+r" (ret), "=&r" (val), "=R" (*uaddr)
167 : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) 168 : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
168 : "memory"); 169 : "memory");
169 } else if (cpu_has_llsc) { 170 } else if (cpu_has_llsc) {
@@ -172,31 +173,32 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
172 " .set push \n" 173 " .set push \n"
173 " .set noat \n" 174 " .set noat \n"
174 " .set mips3 \n" 175 " .set mips3 \n"
175 "1: ll %0, %2 \n" 176 "1: ll %1, %3 \n"
176 " bne %0, %z3, 3f \n" 177 " bne %1, %z4, 3f \n"
177 " .set mips0 \n" 178 " .set mips0 \n"
178 " move $1, %z4 \n" 179 " move $1, %z5 \n"
179 " .set mips3 \n" 180 " .set mips3 \n"
180 "2: sc $1, %1 \n" 181 "2: sc $1, %2 \n"
181 " beqz $1, 1b \n" 182 " beqz $1, 1b \n"
182 __WEAK_LLSC_MB 183 __WEAK_LLSC_MB
183 "3: \n" 184 "3: \n"
184 " .set pop \n" 185 " .set pop \n"
185 " .section .fixup,\"ax\" \n" 186 " .section .fixup,\"ax\" \n"
186 "4: li %0, %5 \n" 187 "4: li %0, %6 \n"
187 " j 3b \n" 188 " j 3b \n"
188 " .previous \n" 189 " .previous \n"
189 " .section __ex_table,\"a\" \n" 190 " .section __ex_table,\"a\" \n"
190 " "__UA_ADDR "\t1b, 4b \n" 191 " "__UA_ADDR "\t1b, 4b \n"
191 " "__UA_ADDR "\t2b, 4b \n" 192 " "__UA_ADDR "\t2b, 4b \n"
192 " .previous \n" 193 " .previous \n"
193 : "=&r" (retval), "=R" (*uaddr) 194 : "+r" (ret), "=&r" (val), "=R" (*uaddr)
194 : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) 195 : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
195 : "memory"); 196 : "memory");
196 } else 197 } else
197 return -ENOSYS; 198 return -ENOSYS;
198 199
199 return retval; 200 *uval = val;
201 return ret;
200} 202}
201 203
202#endif 204#endif