futex: Remove duplicated code and fix undefined behaviour
There is code duplicated over all architecture's headers for futex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr, and comparison of the result. Remove this duplication and leave up to the arches only the needed assembly which is now in arch_futex_atomic_op_inuser. This effectively distributes the Will Deacon's arm64 fix for undefined behaviour reported by UBSAN to all architectures. The fix was done in commit5f16a046f8
(arm64: futex: Fix undefined behaviour with FUTEX_OP_OPARG_SHIFT usage). Look there for an example dump. And as suggested by Thomas, check for negative oparg too, because it was also reported to cause undefined behaviour report. Note that s390 removed access_ok check ind12a29703
("s390/uaccess: remove pointless access_ok() checks") as access_ok there returns true. We introduce it back to the helper for the sake of simplicity (it gets optimized away anyway). Signed-off-by: Jiri Slaby <jslaby@suse.cz> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Russell King <rmk+kernel@armlinux.org.uk> Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc) Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> [s390] Acked-by: Chris Metcalf <cmetcalf@mellanox.com> [for tile] Reviewed-by: Darren Hart (VMware) <dvhart@infradead.org> Reviewed-by: Will Deacon <will.deacon@arm.com> [core/arm64] Cc: linux-mips@linux-mips.org Cc: Rich Felker <dalias@libc.org> Cc: linux-ia64@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: peterz@infradead.org Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Max Filippov <jcmvbkbc@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: sparclinux@vger.kernel.org Cc: Jonas Bonn <jonas@southpole.se> Cc: linux-s390@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: Yoshinori Sato <ysato@users.sourceforge.jp> Cc: linux-hexagon@vger.kernel.org Cc: Helge Deller <deller@gmx.de> Cc: "James E.J. Bottomley" <jejb@parisc-linux.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Matt Turner <mattst88@gmail.com> Cc: linux-snps-arc@lists.infradead.org Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: linux-xtensa@linux-xtensa.org Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> Cc: openrisc@lists.librecores.org Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Cc: Stafford Horne <shorne@gmail.com> Cc: linux-arm-kernel@lists.infradead.org Cc: Richard Henderson <rth@twiddle.net> Cc: Chris Zankel <chris@zankel.net> Cc: Michal Simek <monstr@monstr.eu> Cc: Tony Luck <tony.luck@intel.com> Cc: linux-parisc@vger.kernel.org Cc: Vineet Gupta <vgupta@synopsys.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Richard Kuo <rkuo@codeaurora.org> Cc: linux-alpha@vger.kernel.org Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: linuxppc-dev@lists.ozlabs.org Cc: "David S. Miller" <davem@davemloft.net> Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby@suse.cz
This commit is contained in:
parent
ca110694c6
commit
30d6e0a419
|
@ -25,18 +25,10 @@
|
||||||
: "r" (uaddr), "r"(oparg) \
|
: "r" (uaddr), "r"(oparg) \
|
||||||
: "memory")
|
: "memory")
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -62,17 +54,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,20 +73,11 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
#ifndef CONFIG_ARC_HAS_LLSC
|
#ifndef CONFIG_ARC_HAS_LLSC
|
||||||
preempt_disable(); /* to guarantee atomic r-m-w of futex op */
|
preempt_disable(); /* to guarantee atomic r-m-w of futex op */
|
||||||
#endif
|
#endif
|
||||||
|
@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ:
|
|
||||||
ret = (oldval == cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_NE:
|
|
||||||
ret = (oldval != cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LT:
|
|
||||||
ret = (oldval < cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GE:
|
|
||||||
ret = (oldval >= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LE:
|
|
||||||
ret = (oldval <= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GT:
|
|
||||||
ret = (oldval > cmparg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||||
#endif /* !SMP */
|
#endif /* !SMP */
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret, tmp;
|
int oldval = 0, ret, tmp;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
#endif
|
#endif
|
||||||
|
@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,20 +48,10 @@ do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (int)(encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (int)(encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret, tmp;
|
int oldval = 0, ret, tmp;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1U << (oparg & 0x1f);
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -91,17 +81,9 @@ futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
#include <asm/errno.h>
|
#include <asm/errno.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
|
extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||||
|
u32 __user *uaddr);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||||
|
|
|
@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_o
|
||||||
/*
|
/*
|
||||||
* do the futex operations
|
* do the futex operations
|
||||||
*/
|
*/
|
||||||
int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
} /* end futex_atomic_op_inuser() */
|
} /* end arch_futex_atomic_op_inuser() */
|
||||||
|
|
|
@ -31,18 +31,9 @@
|
||||||
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ:
|
|
||||||
ret = (oldval == cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_NE:
|
|
||||||
ret = (oldval != cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LT:
|
|
||||||
ret = (oldval < cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GE:
|
|
||||||
ret = (oldval >= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LE:
|
|
||||||
ret = (oldval <= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GT:
|
|
||||||
ret = (oldval > cmparg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,18 +45,9 @@ do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,18 +29,9 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ:
|
|
||||||
ret = (oldval == cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_NE:
|
|
||||||
ret = (oldval != cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LT:
|
|
||||||
ret = (oldval < cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GE:
|
|
||||||
ret = (oldval >= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LE:
|
|
||||||
ret = (oldval <= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GT:
|
|
||||||
ret = (oldval > cmparg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,18 +83,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,20 +30,10 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -68,30 +58,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ:
|
|
||||||
ret = (oldval == cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_NE:
|
|
||||||
ret = (oldval != cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LT:
|
|
||||||
ret = (oldval < cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GE:
|
|
||||||
ret = (oldval >= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LE:
|
|
||||||
ret = (oldval <= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GT:
|
|
||||||
ret = (oldval > cmparg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,22 +32,12 @@ _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
unsigned long int flags;
|
unsigned long int flags;
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval, ret;
|
int oldval, ret;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
_futex_spin_lock_irqsave(uaddr, &flags);
|
_futex_spin_lock_irqsave(uaddr, &flags);
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -85,17 +75,9 @@ out_pagefault_enable:
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
_futex_spin_unlock_irqrestore(uaddr, &flags);
|
_futex_spin_unlock_irqrestore(uaddr, &flags);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,18 +29,10 @@
|
||||||
: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
|
: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
|
||||||
: "cr0", "memory")
|
: "cr0", "memory")
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,17 +21,12 @@
|
||||||
: "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
|
: "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
|
||||||
"m" (*uaddr) : "cc");
|
"m" (*uaddr) : "cc");
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, newval, ret;
|
int oldval = 0, newval, ret;
|
||||||
|
|
||||||
load_kernel_asce();
|
load_kernel_asce();
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
}
|
}
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,21 +27,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||||
return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
|
return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
u32 oparg = (encoded_op << 8) >> 20;
|
|
||||||
u32 cmparg = (encoded_op << 20) >> 20;
|
|
||||||
u32 oldval, newval, prev;
|
u32 oldval, newval, prev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -80,17 +71,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = ((int)oldval < (int)cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = ((int)oldval >= (int)cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = ((int)oldval <= (int)cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = ((int)oldval > (int)cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,22 +29,14 @@
|
||||||
: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
|
: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
|
||||||
: "memory")
|
: "memory")
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret, tem;
|
int oldval = 0, ret, tem;
|
||||||
|
|
||||||
if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
|
|
||||||
return -EFAULT;
|
|
||||||
if (unlikely((((unsigned long) uaddr) & 0x3UL)))
|
if (unlikely((((unsigned long) uaddr) & 0x3UL)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,12 +106,9 @@
|
||||||
lock = __atomic_hashed_lock((int __force *)uaddr)
|
lock = __atomic_hashed_lock((int __force *)uaddr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int uninitialized_var(val), ret;
|
int uninitialized_var(val), ret;
|
||||||
|
|
||||||
__futex_prolog();
|
__futex_prolog();
|
||||||
|
@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
/* The 32-bit futex code makes this assumption, so validate it here. */
|
/* The 32-bit futex code makes this assumption, so validate it here. */
|
||||||
BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
|
BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FUTEX_OP_SET:
|
case FUTEX_OP_SET:
|
||||||
|
@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
}
|
}
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = val;
|
||||||
case FUTEX_OP_CMP_EQ:
|
|
||||||
ret = (val == cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_NE:
|
|
||||||
ret = (val != cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LT:
|
|
||||||
ret = (val < cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GE:
|
|
||||||
ret = (val >= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LE:
|
|
||||||
ret = (val <= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GT:
|
|
||||||
ret = (val > cmparg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,20 +41,11 @@
|
||||||
"+m" (*uaddr), "=&r" (tem) \
|
"+m" (*uaddr), "=&r" (tem) \
|
||||||
: "r" (oparg), "i" (-EFAULT), "1" (0))
|
: "r" (oparg), "i" (-EFAULT), "1" (0))
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret, tem;
|
int oldval = 0, ret, tem;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ:
|
|
||||||
ret = (oldval == cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_NE:
|
|
||||||
ret = (oldval != cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LT:
|
|
||||||
ret = (oldval < cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GE:
|
|
||||||
ret = (oldval >= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_LE:
|
|
||||||
ret = (oldval <= cmparg);
|
|
||||||
break;
|
|
||||||
case FUTEX_OP_CMP_GT:
|
|
||||||
ret = (oldval > cmparg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,18 +44,10 @@
|
||||||
: "r" (uaddr), "I" (-EFAULT), "r" (oparg) \
|
: "r" (uaddr), "I" (-EFAULT), "r" (oparg) \
|
||||||
: "memory")
|
: "memory")
|
||||||
|
|
||||||
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
|
||||||
|
u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
#if !XCHAL_HAVE_S32C1I
|
#if !XCHAL_HAVE_S32C1I
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (ret)
|
if (!ret)
|
||||||
return ret;
|
*oval = oldval;
|
||||||
|
|
||||||
switch (cmp) {
|
return ret;
|
||||||
case FUTEX_OP_CMP_EQ: return (oldval == cmparg);
|
|
||||||
case FUTEX_OP_CMP_NE: return (oldval != cmparg);
|
|
||||||
case FUTEX_OP_CMP_LT: return (oldval < cmparg);
|
|
||||||
case FUTEX_OP_CMP_GE: return (oldval >= cmparg);
|
|
||||||
case FUTEX_OP_CMP_LE: return (oldval <= cmparg);
|
|
||||||
case FUTEX_OP_CMP_GT: return (oldval > cmparg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* futex_atomic_op_inuser() - Atomic arithmetic operation with constant
|
* arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant
|
||||||
* argument and comparison of the previous
|
* argument and comparison of the previous
|
||||||
* futex value with another constant.
|
* futex value with another constant.
|
||||||
*
|
*
|
||||||
|
@ -25,18 +25,11 @@
|
||||||
* <0 - On error
|
* <0 - On error
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval, ret;
|
int oldval, ret;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -74,17 +67,9 @@ out_pagefault_enable:
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static inline int
|
static inline int
|
||||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
|
||||||
{
|
{
|
||||||
int op = (encoded_op >> 28) & 7;
|
|
||||||
int cmp = (encoded_op >> 24) & 15;
|
|
||||||
int oparg = (encoded_op << 8) >> 20;
|
|
||||||
int cmparg = (encoded_op << 20) >> 20;
|
|
||||||
int oldval = 0, ret;
|
int oldval = 0, ret;
|
||||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
||||||
oparg = 1 << oparg;
|
|
||||||
|
|
||||||
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
|
@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
switch (cmp) {
|
*oval = oldval;
|
||||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
|
||||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
|
||||||
default: ret = -ENOSYS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1551,6 +1551,45 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
|
||||||
|
{
|
||||||
|
unsigned int op = (encoded_op & 0x70000000) >> 28;
|
||||||
|
unsigned int cmp = (encoded_op & 0x0f000000) >> 24;
|
||||||
|
int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);
|
||||||
|
int cmparg = sign_extend32(encoded_op & 0x00000fff, 12);
|
||||||
|
int oldval, ret;
|
||||||
|
|
||||||
|
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {
|
||||||
|
if (oparg < 0 || oparg > 31)
|
||||||
|
return -EINVAL;
|
||||||
|
oparg = 1 << oparg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
switch (cmp) {
|
||||||
|
case FUTEX_OP_CMP_EQ:
|
||||||
|
return oldval == cmparg;
|
||||||
|
case FUTEX_OP_CMP_NE:
|
||||||
|
return oldval != cmparg;
|
||||||
|
case FUTEX_OP_CMP_LT:
|
||||||
|
return oldval < cmparg;
|
||||||
|
case FUTEX_OP_CMP_GE:
|
||||||
|
return oldval >= cmparg;
|
||||||
|
case FUTEX_OP_CMP_LE:
|
||||||
|
return oldval <= cmparg;
|
||||||
|
case FUTEX_OP_CMP_GT:
|
||||||
|
return oldval > cmparg;
|
||||||
|
default:
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wake up all waiters hashed on the physical page that is mapped
|
* Wake up all waiters hashed on the physical page that is mapped
|
||||||
* to this virtual address:
|
* to this virtual address:
|
||||||
|
|
Loading…
Reference in New Issue