diff options
author | Michel Lespinasse <walken@google.com> | 2011-03-10 21:48:51 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2011-03-11 06:23:08 -0500 |
commit | 37a9d912b24f96a0591773e6e6c3642991ae5a70 (patch) | |
tree | 5c4d5b9a52e2c533269e589115afbd25b6c8534b /arch/mips | |
parent | 522d7decc0370070448a8c28982c8dfd8970489e (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.h | 32 |
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 | ||
134 | static inline int | 134 | static inline int |
135 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | 135 | futex_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 |