diff for duplicates of <15265499332582@kroah.com> diff --git a/a/content_digest b/N1/content_digest index a9fcf82..1c6c9de 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -18,8 +18,7 @@ ink@jurassic.park.msu.ru jcmvbkbc@gmail.com jejb@parisc-linux.org - jonas@southpole.se - jslaby@suse.cz + jonas@southpole.sejslaby@suse.cz linux-arm-kernel@lists.infradead.org linux-mips@linux-mips.org linux-snps-arc@lists.infradead.org @@ -43,7 +42,7 @@ vgupta@synopsys.com will.deacon@arm.com " ysato@users.sourceforge.jp\0" - "Cc\0<stable-commits@vger.kernel.org>\0" + "Cc\0stable-commits@vger.kernel.org\0" "\00:1\0" "b\0" "\n" @@ -61,4 +60,4 @@ "If you, or anyone else, feels it should not be added to the stable tree,\n" please let <stable@vger.kernel.org> know about it. -f87e12fcc4b63fa4f725f8fcbd2ab6c4f98754ab10827b6719644b9c25712681 +392a6c2823da6c09733492b06e366cbae5a62af63fbe565a9001dd0f4d35ee36
diff --git a/a/1.txt b/N2/1.txt index d6bf5c4..4f7515c 100644 --- a/a/1.txt +++ b/N2/1.txt @@ -11,4 +11,1098 @@ The filename of the patch is: and it can be found in the queue-4.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, -please let <stable@vger.kernel.org> know about it. +please let <stable at vger.kernel.org> know about it. + + +>From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby <jslaby@suse.cz> +Date: Thu, 24 Aug 2017 09:31:05 +0200 +Subject: futex: Remove duplicated code and fix undefined behaviour + +From: Jiri Slaby <jslaby@suse.cz> + +commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream. + +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 +commit 5f16a046f8e1 (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 in d12a29703 ("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 at suse.cz> +Signed-off-by: Thomas Gleixner <tglx at linutronix.de> +Acked-by: Russell King <rmk+kernel at armlinux.org.uk> +Acked-by: Michael Ellerman <mpe at ellerman.id.au> (powerpc) +Acked-by: Heiko Carstens <heiko.carstens at de.ibm.com> [s390] +Acked-by: Chris Metcalf <cmetcalf at mellanox.com> [for tile] +Reviewed-by: Darren Hart (VMware) <dvhart at infradead.org> +Reviewed-by: Will Deacon <will.deacon at arm.com> [core/arm64] +Cc: linux-mips at linux-mips.org +Cc: Rich Felker <dalias at libc.org> +Cc: linux-ia64 at vger.kernel.org +Cc: linux-sh at vger.kernel.org +Cc: peterz at infradead.org +Cc: Benjamin Herrenschmidt <benh at kernel.crashing.org> +Cc: Max Filippov <jcmvbkbc at gmail.com> +Cc: Paul Mackerras <paulus at samba.org> +Cc: sparclinux at vger.kernel.org +Cc: Jonas Bonn <jonas at southpole.se> +Cc: linux-s390 at vger.kernel.org +Cc: linux-arch at vger.kernel.org +Cc: Yoshinori Sato <ysato at users.sourceforge.jp> +Cc: linux-hexagon at vger.kernel.org +Cc: Helge Deller <deller at gmx.de> +Cc: "James E.J. Bottomley" <jejb at parisc-linux.org> +Cc: Catalin Marinas <catalin.marinas at arm.com> +Cc: Matt Turner <mattst88 at gmail.com> +Cc: linux-snps-arc at lists.infradead.org +Cc: Fenghua Yu <fenghua.yu at intel.com> +Cc: Arnd Bergmann <arnd at arndb.de> +Cc: linux-xtensa at linux-xtensa.org +Cc: Stefan Kristiansson <stefan.kristiansson at saunalahti.fi> +Cc: openrisc at lists.librecores.org +Cc: Ivan Kokshaysky <ink at jurassic.park.msu.ru> +Cc: Stafford Horne <shorne at gmail.com> +Cc: linux-arm-kernel at lists.infradead.org +Cc: Richard Henderson <rth at twiddle.net> +Cc: Chris Zankel <chris at zankel.net> +Cc: Michal Simek <monstr at monstr.eu> +Cc: Tony Luck <tony.luck at intel.com> +Cc: linux-parisc at vger.kernel.org +Cc: Vineet Gupta <vgupta at synopsys.com> +Cc: Ralf Baechle <ralf at linux-mips.org> +Cc: Richard Kuo <rkuo at codeaurora.org> +Cc: linux-alpha at vger.kernel.org +Cc: Martin Schwidefsky <schwidefsky at de.ibm.com> +Cc: linuxppc-dev at lists.ozlabs.org +Cc: "David S. Miller" <davem at davemloft.net> +Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby at suse.cz +Cc: Ben Hutchings <ben.hutchings at codethink.co.uk> +Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org> + +--- + arch/alpha/include/asm/futex.h | 26 +++--------------- + arch/arc/include/asm/futex.h | 40 +++------------------------- + arch/arm/include/asm/futex.h | 26 ++---------------- + arch/arm64/include/asm/futex.h | 26 ++---------------- + arch/frv/include/asm/futex.h | 3 +- + arch/frv/kernel/futex.c | 27 ++----------------- + arch/hexagon/include/asm/futex.h | 38 ++------------------------- + arch/ia64/include/asm/futex.h | 25 ++---------------- + arch/microblaze/include/asm/futex.h | 38 ++------------------------- + arch/mips/include/asm/futex.h | 25 ++---------------- + arch/parisc/include/asm/futex.h | 25 ++---------------- + arch/powerpc/include/asm/futex.h | 26 +++--------------- + arch/s390/include/asm/futex.h | 23 +++------------- + arch/sh/include/asm/futex.h | 26 ++---------------- + arch/sparc/include/asm/futex_64.h | 26 +++--------------- + arch/tile/include/asm/futex.h | 40 +++------------------------- + arch/x86/include/asm/futex.h | 40 +++------------------------- + arch/xtensa/include/asm/futex.h | 27 +++---------------- + include/asm-generic/futex.h | 50 ++++++------------------------------ + kernel/futex.c | 39 ++++++++++++++++++++++++++++ + 20 files changed, 126 insertions(+), 470 deletions(-) + +--- a/arch/alpha/include/asm/futex.h ++++ b/arch/alpha/include/asm/futex.h +@@ -29,18 +29,10 @@ + : "r" (uaddr), "r"(oparg) \ + : "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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arc/include/asm/futex.h ++++ b/arch/arc/include/asm/futex.h +@@ -73,20 +73,11 @@ + + #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; + +- 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 + preempt_disable(); /* to guarantee atomic r-m-w of futex op */ + #endif +@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + #endif /* !SMP */ + + 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + #ifndef CONFIG_SMP + preempt_disable(); + #endif +@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm64/include/asm/futex.h ++++ b/arch/arm64/include/asm/futex.h +@@ -53,20 +53,10 @@ + : "memory") + + 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1U << (oparg & 0x1f); +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/frv/include/asm/futex.h ++++ b/arch/frv/include/asm/futex.h +@@ -7,7 +7,8 @@ + #include <asm/errno.h> + #include <asm/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 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +--- a/arch/frv/kernel/futex.c ++++ b/arch/frv/kernel/futex.c +@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x + /* + * 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + +-} /* end futex_atomic_op_inuser() */ ++} /* end arch_futex_atomic_op_inuser() */ +--- a/arch/hexagon/include/asm/futex.h ++++ b/arch/hexagon/include/asm/futex.h +@@ -31,18 +31,9 @@ + + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) +- return -EFAULT; + + pagefault_disable(); + +@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/ia64/include/asm/futex.h ++++ b/arch/ia64/include/asm/futex.h +@@ -45,18 +45,9 @@ do { \ + } while (0) + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/microblaze/include/asm/futex.h ++++ b/arch/microblaze/include/asm/futex.h +@@ -29,18 +29,9 @@ + }) + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/mips/include/asm/futex.h ++++ b/arch/mips/include/asm/futex.h +@@ -83,18 +83,9 @@ + } + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/parisc/include/asm/futex.h ++++ b/arch/parisc/include/asm/futex.h +@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user + } + + 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; + u32 val; +- 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr))) +- return -EFAULT; + + pagefault_disable(); + +@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/powerpc/include/asm/futex.h ++++ b/arch/powerpc/include/asm/futex.h +@@ -31,18 +31,10 @@ + : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ + : "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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/s390/include/asm/futex.h ++++ b/arch/s390/include/asm/futex.h +@@ -21,17 +21,12 @@ + : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ + "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; + + load_kernel_asce(); +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; + + pagefault_disable(); + switch (op) { +@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/sh/include/asm/futex.h ++++ b/arch/sh/include/asm/futex.h +@@ -10,20 +10,11 @@ + /* XXX: UP variants, fix for SH-4A and SMP.. */ + #include <asm/futex-irq.h> + +-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 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(); + + switch (op) { +@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + } +--- a/arch/sparc/include/asm/futex_64.h ++++ b/arch/sparc/include/asm/futex_64.h +@@ -29,22 +29,14 @@ + : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ + : "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; + +- if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) +- return -EFAULT; + if (unlikely((((unsigned long) uaddr) & 0x3UL))) + return -EINVAL; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + pagefault_disable(); + + switch (op) { +@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/tile/include/asm/futex.h ++++ b/arch/tile/include/asm/futex.h +@@ -106,12 +106,9 @@ + lock = __atomic_hashed_lock((int __force *)uaddr) + #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; + + __futex_prolog(); +@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser + /* The 32-bit futex code makes this assumption, so validate it here. */ + 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(); + switch (op) { + case FUTEX_OP_SET: +@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = val; ++ + return ret; + } + +--- a/arch/x86/include/asm/futex.h ++++ b/arch/x86/include/asm/futex.h +@@ -41,20 +41,11 @@ + "+m" (*uaddr), "=&r" (tem) \ + : "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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/xtensa/include/asm/futex.h ++++ b/arch/xtensa/include/asm/futex.h +@@ -44,18 +44,10 @@ + : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \ + : "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; +- 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 + return -ENOSYS; +@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- 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); +- } ++ if (!ret) ++ *oval = oldval; + +- return -ENOSYS; ++ return ret; + } + + static inline int +--- a/include/asm-generic/futex.h ++++ b/include/asm-generic/futex.h +@@ -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 + * futex value with another constant. + * +@@ -25,18 +25,11 @@ + * <0 - On error + */ + 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; + u32 tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + preempt_disable(); + pagefault_disable(); + +@@ -74,17 +67,9 @@ out_pagefault_enable: + pagefault_enable(); + preempt_enable(); + +- if (ret == 0) { +- switch (cmp) { +- 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; +- } +- } ++ if (ret == 0) ++ *oval = oldval; ++ + return ret; + } + +@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + + #else + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1453,6 +1453,45 @@ out: + 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 + * to this virtual address: + + +Patches currently in stable-queue which might be from jslaby at suse.cz are + +queue-4.4/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch diff --git a/a/content_digest b/N2/content_digest index a9fcf82..7b47061 100644 --- a/a/content_digest +++ b/N2/content_digest @@ -1,49 +1,7 @@ - "From\0<gregkh@linuxfoundation.org>\0" + "From\0gregkh@linuxfoundation.org (gregkh@linuxfoundation.org)\0" "Subject\0Patch \"futex: Remove duplicated code and fix undefined behaviour\" has been added to the 4.4-stable tree\0" "Date\0Thu, 17 May 2018 11:38:53 +0200\0" - "To\020170824073105.3901-1-jslaby@suse.cz" - arnd@arndb.de - ben.hutchings@codethink.co.uk - benh@kernel.crashing.org - catalin.marinas@arm.com - chris@zankel.net - cmetcalf@mellanox.com - dalias@libc.org - davem@davemloft.net - deller@gmx.de - dvhart@infradead.org - fenghua.yu@intel.com - gregkh@linuxfoundation.org - heiko.carstens@de.ibm.com - ink@jurassic.park.msu.ru - jcmvbkbc@gmail.com - jejb@parisc-linux.org - jonas@southpole.se - jslaby@suse.cz - linux-arm-kernel@lists.infradead.org - linux-mips@linux-mips.org - linux-snps-arc@lists.infradead.org - linux-xtensa@linux-xtensa.org - linuxppc-dev@lists.ozlabs.org - mattst88@gmail.com - monstr@monstr.eu - mpe@ellerman.id.au - openrisc@lists.librecores.org - paulus@samba.org - peterz@infradead.org - ralf@linux-mips.org - rkuo@codeaurora.org - rmk+kernel@armlinux.org.uk - rth@twiddle.net - schwidefsky@de.ibm.com - shorne@gmail.com - stefan.kristiansson@saunalahti.fi - tglx@linutronix.de - tony.luck@intel.com - vgupta@synopsys.com - will.deacon@arm.com - " ysato@users.sourceforge.jp\0" - "Cc\0<stable-commits@vger.kernel.org>\0" + "To\0linux-snps-arc@lists.infradead.org\0" "\00:1\0" "b\0" "\n" @@ -59,6 +17,1100 @@ "and it can be found in the queue-4.4 subdirectory.\n" "\n" "If you, or anyone else, feels it should not be added to the stable tree,\n" - please let <stable@vger.kernel.org> know about it. + "please let <stable at vger.kernel.org> know about it.\n" + "\n" + "\n" + ">From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001\n" + "From: Jiri Slaby <jslaby@suse.cz>\n" + "Date: Thu, 24 Aug 2017 09:31:05 +0200\n" + "Subject: futex: Remove duplicated code and fix undefined behaviour\n" + "\n" + "From: Jiri Slaby <jslaby@suse.cz>\n" + "\n" + "commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream.\n" + "\n" + "There is code duplicated over all architecture's headers for\n" + "futex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr,\n" + "and comparison of the result.\n" + "\n" + "Remove this duplication and leave up to the arches only the needed\n" + "assembly which is now in arch_futex_atomic_op_inuser.\n" + "\n" + "This effectively distributes the Will Deacon's arm64 fix for undefined\n" + "behaviour reported by UBSAN to all architectures. The fix was done in\n" + "commit 5f16a046f8e1 (arm64: futex: Fix undefined behaviour with\n" + "FUTEX_OP_OPARG_SHIFT usage). Look there for an example dump.\n" + "\n" + "And as suggested by Thomas, check for negative oparg too, because it was\n" + "also reported to cause undefined behaviour report.\n" + "\n" + "Note that s390 removed access_ok check in d12a29703 (\"s390/uaccess:\n" + "remove pointless access_ok() checks\") as access_ok there returns true.\n" + "We introduce it back to the helper for the sake of simplicity (it gets\n" + "optimized away anyway).\n" + "\n" + "Signed-off-by: Jiri Slaby <jslaby at suse.cz>\n" + "Signed-off-by: Thomas Gleixner <tglx at linutronix.de>\n" + "Acked-by: Russell King <rmk+kernel at armlinux.org.uk>\n" + "Acked-by: Michael Ellerman <mpe at ellerman.id.au> (powerpc)\n" + "Acked-by: Heiko Carstens <heiko.carstens at de.ibm.com> [s390]\n" + "Acked-by: Chris Metcalf <cmetcalf at mellanox.com> [for tile]\n" + "Reviewed-by: Darren Hart (VMware) <dvhart at infradead.org>\n" + "Reviewed-by: Will Deacon <will.deacon at arm.com> [core/arm64]\n" + "Cc: linux-mips at linux-mips.org\n" + "Cc: Rich Felker <dalias at libc.org>\n" + "Cc: linux-ia64 at vger.kernel.org\n" + "Cc: linux-sh at vger.kernel.org\n" + "Cc: peterz at infradead.org\n" + "Cc: Benjamin Herrenschmidt <benh at kernel.crashing.org>\n" + "Cc: Max Filippov <jcmvbkbc at gmail.com>\n" + "Cc: Paul Mackerras <paulus at samba.org>\n" + "Cc: sparclinux at vger.kernel.org\n" + "Cc: Jonas Bonn <jonas at southpole.se>\n" + "Cc: linux-s390 at vger.kernel.org\n" + "Cc: linux-arch at vger.kernel.org\n" + "Cc: Yoshinori Sato <ysato at users.sourceforge.jp>\n" + "Cc: linux-hexagon at vger.kernel.org\n" + "Cc: Helge Deller <deller at gmx.de>\n" + "Cc: \"James E.J. Bottomley\" <jejb at parisc-linux.org>\n" + "Cc: Catalin Marinas <catalin.marinas at arm.com>\n" + "Cc: Matt Turner <mattst88 at gmail.com>\n" + "Cc: linux-snps-arc at lists.infradead.org\n" + "Cc: Fenghua Yu <fenghua.yu at intel.com>\n" + "Cc: Arnd Bergmann <arnd at arndb.de>\n" + "Cc: linux-xtensa at linux-xtensa.org\n" + "Cc: Stefan Kristiansson <stefan.kristiansson at saunalahti.fi>\n" + "Cc: openrisc at lists.librecores.org\n" + "Cc: Ivan Kokshaysky <ink at jurassic.park.msu.ru>\n" + "Cc: Stafford Horne <shorne at gmail.com>\n" + "Cc: linux-arm-kernel at lists.infradead.org\n" + "Cc: Richard Henderson <rth at twiddle.net>\n" + "Cc: Chris Zankel <chris at zankel.net>\n" + "Cc: Michal Simek <monstr at monstr.eu>\n" + "Cc: Tony Luck <tony.luck at intel.com>\n" + "Cc: linux-parisc at vger.kernel.org\n" + "Cc: Vineet Gupta <vgupta at synopsys.com>\n" + "Cc: Ralf Baechle <ralf at linux-mips.org>\n" + "Cc: Richard Kuo <rkuo at codeaurora.org>\n" + "Cc: linux-alpha at vger.kernel.org\n" + "Cc: Martin Schwidefsky <schwidefsky at de.ibm.com>\n" + "Cc: linuxppc-dev at lists.ozlabs.org\n" + "Cc: \"David S. Miller\" <davem at davemloft.net>\n" + "Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby at suse.cz\n" + "Cc: Ben Hutchings <ben.hutchings at codethink.co.uk>\n" + "Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>\n" + "\n" + "---\n" + " arch/alpha/include/asm/futex.h | 26 +++---------------\n" + " arch/arc/include/asm/futex.h | 40 +++-------------------------\n" + " arch/arm/include/asm/futex.h | 26 ++----------------\n" + " arch/arm64/include/asm/futex.h | 26 ++----------------\n" + " arch/frv/include/asm/futex.h | 3 +-\n" + " arch/frv/kernel/futex.c | 27 ++-----------------\n" + " arch/hexagon/include/asm/futex.h | 38 ++-------------------------\n" + " arch/ia64/include/asm/futex.h | 25 ++----------------\n" + " arch/microblaze/include/asm/futex.h | 38 ++-------------------------\n" + " arch/mips/include/asm/futex.h | 25 ++----------------\n" + " arch/parisc/include/asm/futex.h | 25 ++----------------\n" + " arch/powerpc/include/asm/futex.h | 26 +++---------------\n" + " arch/s390/include/asm/futex.h | 23 +++-------------\n" + " arch/sh/include/asm/futex.h | 26 ++----------------\n" + " arch/sparc/include/asm/futex_64.h | 26 +++---------------\n" + " arch/tile/include/asm/futex.h | 40 +++-------------------------\n" + " arch/x86/include/asm/futex.h | 40 +++-------------------------\n" + " arch/xtensa/include/asm/futex.h | 27 +++----------------\n" + " include/asm-generic/futex.h | 50 ++++++------------------------------\n" + " kernel/futex.c | 39 ++++++++++++++++++++++++++++\n" + " 20 files changed, 126 insertions(+), 470 deletions(-)\n" + "\n" + "--- a/arch/alpha/include/asm/futex.h\n" + "+++ b/arch/alpha/include/asm/futex.h\n" + "@@ -29,18 +29,10 @@\n" + " \t:\t\"r\" (uaddr), \"r\"(oparg)\t\t\t\t\\\n" + " \t:\t\"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arc/include/asm/futex.h\n" + "+++ b/arch/arc/include/asm/futex.h\n" + "@@ -73,20 +73,11 @@\n" + " \n" + " #endif\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " #ifndef CONFIG_ARC_HAS_LLSC\n" + " \tpreempt_disable();\t/* to guarantee atomic r-m-w of futex op */\n" + " #endif\n" + "@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser\n" + " \tpreempt_enable();\n" + " #endif\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arm/include/asm/futex.h\n" + "+++ b/arch/arm/include/asm/futex.h\n" + "@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,\n" + " #endif /* !SMP */\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " #ifndef CONFIG_SMP\n" + " \tpreempt_disable();\n" + " #endif\n" + "@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \tpreempt_enable();\n" + " #endif\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arm64/include/asm/futex.h\n" + "+++ b/arch/arm64/include/asm/futex.h\n" + "@@ -53,20 +53,10 @@\n" + " \t: \"memory\")\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (int)(encoded_op << 8) >> 20;\n" + "-\tint cmparg = (int)(encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1U << (oparg & 0x1f);\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/frv/include/asm/futex.h\n" + "+++ b/arch/frv/include/asm/futex.h\n" + "@@ -7,7 +7,8 @@\n" + " #include <asm/errno.h>\n" + " #include <asm/uaccess.h>\n" + " \n" + "-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);\n" + "+extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr);\n" + " \n" + " static inline int\n" + " futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,\n" + "--- a/arch/frv/kernel/futex.c\n" + "+++ b/arch/frv/kernel/futex.c\n" + "@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x\n" + " /*\n" + " * do the futex operations\n" + " */\n" + "-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS; break;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + " \treturn ret;\n" + " \n" + "-} /* end futex_atomic_op_inuser() */\n" + "+} /* end arch_futex_atomic_op_inuser() */\n" + "--- a/arch/hexagon/include/asm/futex.h\n" + "+++ b/arch/hexagon/include/asm/futex.h\n" + "@@ -31,18 +31,9 @@\n" + " \n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/ia64/include/asm/futex.h\n" + "+++ b/arch/ia64/include/asm/futex.h\n" + "@@ -45,18 +45,9 @@ do {\t\t\t\t\t\t\t\t\t\\\n" + " } while (0)\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/microblaze/include/asm/futex.h\n" + "+++ b/arch/microblaze/include/asm/futex.h\n" + "@@ -29,18 +29,9 @@\n" + " })\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/mips/include/asm/futex.h\n" + "+++ b/arch/mips/include/asm/futex.h\n" + "@@ -83,18 +83,9 @@\n" + " }\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/parisc/include/asm/futex.h\n" + "+++ b/arch/parisc/include/asm/futex.h\n" + "@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user\n" + " }\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + " \tunsigned long int flags;\n" + " \tu32 val;\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/powerpc/include/asm/futex.h\n" + "+++ b/arch/powerpc/include/asm/futex.h\n" + "@@ -31,18 +31,10 @@\n" + " \t: \"b\" (uaddr), \"i\" (-EFAULT), \"r\" (oparg) \\\n" + " \t: \"cr0\", \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/s390/include/asm/futex.h\n" + "+++ b/arch/s390/include/asm/futex.h\n" + "@@ -21,17 +21,12 @@\n" + " \t\t: \"0\" (-EFAULT), \"d\" (oparg), \"a\" (uaddr),\t\t\\\n" + " \t\t \"m\" (*uaddr) : \"cc\");\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, newval, ret;\n" + " \n" + " \tload_kernel_asce();\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + " \n" + " \tpagefault_disable();\n" + " \tswitch (op) {\n" + "@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser\n" + " \t}\n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/sh/include/asm/futex.h\n" + "+++ b/arch/sh/include/asm/futex.h\n" + "@@ -10,20 +10,11 @@\n" + " /* XXX: UP variants, fix for SH-4A and SMP.. */\n" + " #include <asm/futex-irq.h>\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + " \treturn ret;\n" + " }\n" + "--- a/arch/sparc/include/asm/futex_64.h\n" + "+++ b/arch/sparc/include/asm/futex_64.h\n" + "@@ -29,22 +29,14 @@\n" + " \t: \"r\" (uaddr), \"r\" (oparg), \"i\" (-EFAULT)\t\\\n" + " \t: \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tem;\n" + " \n" + "-\tif (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))\n" + "-\t\treturn -EFAULT;\n" + " \tif (unlikely((((unsigned long) uaddr) & 0x3UL)))\n" + " \t\treturn -EINVAL;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/tile/include/asm/futex.h\n" + "+++ b/arch/tile/include/asm/futex.h\n" + "@@ -106,12 +106,9 @@\n" + " \tlock = __atomic_hashed_lock((int __force *)uaddr)\n" + " #endif\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint uninitialized_var(val), ret;\n" + " \n" + " \t__futex_prolog();\n" + "@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser\n" + " \t/* The 32-bit futex code makes this assumption, so validate it here. */\n" + " \tBUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \tswitch (op) {\n" + " \tcase FUTEX_OP_SET:\n" + "@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser\n" + " \t}\n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (val == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (val != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (val < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (val >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (val <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (val > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = val;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/x86/include/asm/futex.h\n" + "+++ b/arch/x86/include/asm/futex.h\n" + "@@ -41,20 +41,11 @@\n" + " \t\t \"+m\" (*uaddr), \"=&r\" (tem)\t\t\\\n" + " \t\t : \"r\" (oparg), \"i\" (-EFAULT), \"1\" (0))\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tem;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/xtensa/include/asm/futex.h\n" + "+++ b/arch/xtensa/include/asm/futex.h\n" + "@@ -44,18 +44,10 @@\n" + " \t: \"r\" (uaddr), \"I\" (-EFAULT), \"r\" (oparg)\t\\\n" + " \t: \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " #if !XCHAL_HAVE_S32C1I\n" + " \treturn -ENOSYS;\n" + "@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (ret)\n" + "-\t\treturn ret;\n" + "-\n" + "-\tswitch (cmp) {\n" + "-\tcase FUTEX_OP_CMP_EQ: return (oldval == cmparg);\n" + "-\tcase FUTEX_OP_CMP_NE: return (oldval != cmparg);\n" + "-\tcase FUTEX_OP_CMP_LT: return (oldval < cmparg);\n" + "-\tcase FUTEX_OP_CMP_GE: return (oldval >= cmparg);\n" + "-\tcase FUTEX_OP_CMP_LE: return (oldval <= cmparg);\n" + "-\tcase FUTEX_OP_CMP_GT: return (oldval > cmparg);\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + "-\treturn -ENOSYS;\n" + "+\treturn ret;\n" + " }\n" + " \n" + " static inline int\n" + "--- a/include/asm-generic/futex.h\n" + "+++ b/include/asm-generic/futex.h\n" + "@@ -13,7 +13,7 @@\n" + " */\n" + " \n" + " /**\n" + "- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n" + "+ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n" + " *\t\t\t argument and comparison of the previous\n" + " *\t\t\t futex value with another constant.\n" + " *\n" + "@@ -25,18 +25,11 @@\n" + " * <0 - On error\n" + " */\n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval, ret;\n" + " \tu32 tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + " \tpreempt_disable();\n" + " \tpagefault_disable();\n" + " \n" + "@@ -74,17 +67,9 @@ out_pagefault_enable:\n" + " \tpagefault_enable();\n" + " \tpreempt_enable();\n" + " \n" + "-\tif (ret == 0) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (ret == 0)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,\n" + " \n" + " #else\n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/kernel/futex.c\n" + "+++ b/kernel/futex.c\n" + "@@ -1453,6 +1453,45 @@ out:\n" + " \treturn ret;\n" + " }\n" + " \n" + "+static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n" + "+{\n" + "+\tunsigned int op =\t (encoded_op & 0x70000000) >> 28;\n" + "+\tunsigned int cmp =\t (encoded_op & 0x0f000000) >> 24;\n" + "+\tint oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);\n" + "+\tint cmparg = sign_extend32(encoded_op & 0x00000fff, 12);\n" + "+\tint oldval, ret;\n" + "+\n" + "+\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {\n" + "+\t\tif (oparg < 0 || oparg > 31)\n" + "+\t\t\treturn -EINVAL;\n" + "+\t\toparg = 1 << oparg;\n" + "+\t}\n" + "+\n" + "+\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "+\t\treturn -EFAULT;\n" + "+\n" + "+\tret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);\n" + "+\tif (ret)\n" + "+\t\treturn ret;\n" + "+\n" + "+\tswitch (cmp) {\n" + "+\tcase FUTEX_OP_CMP_EQ:\n" + "+\t\treturn oldval == cmparg;\n" + "+\tcase FUTEX_OP_CMP_NE:\n" + "+\t\treturn oldval != cmparg;\n" + "+\tcase FUTEX_OP_CMP_LT:\n" + "+\t\treturn oldval < cmparg;\n" + "+\tcase FUTEX_OP_CMP_GE:\n" + "+\t\treturn oldval >= cmparg;\n" + "+\tcase FUTEX_OP_CMP_LE:\n" + "+\t\treturn oldval <= cmparg;\n" + "+\tcase FUTEX_OP_CMP_GT:\n" + "+\t\treturn oldval > cmparg;\n" + "+\tdefault:\n" + "+\t\treturn -ENOSYS;\n" + "+\t}\n" + "+}\n" + "+\n" + " /*\n" + " * Wake up all waiters hashed on the physical page that is mapped\n" + " * to this virtual address:\n" + "\n" + "\n" + "Patches currently in stable-queue which might be from jslaby at suse.cz are\n" + "\n" + queue-4.4/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch -f87e12fcc4b63fa4f725f8fcbd2ab6c4f98754ab10827b6719644b9c25712681 +c7c09080fe133f495f22d26b56346ad25295cf8df6bb193e53540de025b24135
diff --git a/a/1.txt b/N3/1.txt index d6bf5c4..6fb1d42 100644 --- a/a/1.txt +++ b/N3/1.txt @@ -12,3 +12,1097 @@ and it can be found in the queue-4.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@vger.kernel.org> know about it. + + +From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby <jslaby@suse.cz> +Date: Thu, 24 Aug 2017 09:31:05 +0200 +Subject: futex: Remove duplicated code and fix undefined behaviour + +From: Jiri Slaby <jslaby@suse.cz> + +commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream. + +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 +commit 5f16a046f8e1 (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 in d12a29703 ("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 at linux-mips.org +Cc: Rich Felker <dalias@libc.org> +Cc: linux-ia64 at vger.kernel.org +Cc: linux-sh at vger.kernel.org +Cc: peterz at infradead.org +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Max Filippov <jcmvbkbc@gmail.com> +Cc: Paul Mackerras <paulus@samba.org> +Cc: sparclinux at vger.kernel.org +Cc: Jonas Bonn <jonas@southpole.se> +Cc: linux-s390 at vger.kernel.org +Cc: linux-arch at vger.kernel.org +Cc: Yoshinori Sato <ysato@users.sourceforge.jp> +Cc: linux-hexagon at 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 at lists.infradead.org +Cc: Fenghua Yu <fenghua.yu@intel.com> +Cc: Arnd Bergmann <arnd@arndb.de> +Cc: linux-xtensa at linux-xtensa.org +Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> +Cc: openrisc at lists.librecores.org +Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> +Cc: Stafford Horne <shorne@gmail.com> +Cc: linux-arm-kernel at 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 at 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 at vger.kernel.org +Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> +Cc: linuxppc-dev at lists.ozlabs.org +Cc: "David S. Miller" <davem@davemloft.net> +Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby at suse.cz +Cc: Ben Hutchings <ben.hutchings@codethink.co.uk> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + +--- + arch/alpha/include/asm/futex.h | 26 +++--------------- + arch/arc/include/asm/futex.h | 40 +++------------------------- + arch/arm/include/asm/futex.h | 26 ++---------------- + arch/arm64/include/asm/futex.h | 26 ++---------------- + arch/frv/include/asm/futex.h | 3 +- + arch/frv/kernel/futex.c | 27 ++----------------- + arch/hexagon/include/asm/futex.h | 38 ++------------------------- + arch/ia64/include/asm/futex.h | 25 ++---------------- + arch/microblaze/include/asm/futex.h | 38 ++------------------------- + arch/mips/include/asm/futex.h | 25 ++---------------- + arch/parisc/include/asm/futex.h | 25 ++---------------- + arch/powerpc/include/asm/futex.h | 26 +++--------------- + arch/s390/include/asm/futex.h | 23 +++------------- + arch/sh/include/asm/futex.h | 26 ++---------------- + arch/sparc/include/asm/futex_64.h | 26 +++--------------- + arch/tile/include/asm/futex.h | 40 +++------------------------- + arch/x86/include/asm/futex.h | 40 +++------------------------- + arch/xtensa/include/asm/futex.h | 27 +++---------------- + include/asm-generic/futex.h | 50 ++++++------------------------------ + kernel/futex.c | 39 ++++++++++++++++++++++++++++ + 20 files changed, 126 insertions(+), 470 deletions(-) + +--- a/arch/alpha/include/asm/futex.h ++++ b/arch/alpha/include/asm/futex.h +@@ -29,18 +29,10 @@ + : "r" (uaddr), "r"(oparg) \ + : "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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arc/include/asm/futex.h ++++ b/arch/arc/include/asm/futex.h +@@ -73,20 +73,11 @@ + + #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; + +- 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 + preempt_disable(); /* to guarantee atomic r-m-w of futex op */ + #endif +@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + #endif /* !SMP */ + + 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + #ifndef CONFIG_SMP + preempt_disable(); + #endif +@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm64/include/asm/futex.h ++++ b/arch/arm64/include/asm/futex.h +@@ -53,20 +53,10 @@ + : "memory") + + 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1U << (oparg & 0x1f); +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/frv/include/asm/futex.h ++++ b/arch/frv/include/asm/futex.h +@@ -7,7 +7,8 @@ + #include <asm/errno.h> + #include <asm/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 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +--- a/arch/frv/kernel/futex.c ++++ b/arch/frv/kernel/futex.c +@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x + /* + * 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + +-} /* end futex_atomic_op_inuser() */ ++} /* end arch_futex_atomic_op_inuser() */ +--- a/arch/hexagon/include/asm/futex.h ++++ b/arch/hexagon/include/asm/futex.h +@@ -31,18 +31,9 @@ + + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) +- return -EFAULT; + + pagefault_disable(); + +@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/ia64/include/asm/futex.h ++++ b/arch/ia64/include/asm/futex.h +@@ -45,18 +45,9 @@ do { \ + } while (0) + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/microblaze/include/asm/futex.h ++++ b/arch/microblaze/include/asm/futex.h +@@ -29,18 +29,9 @@ + }) + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/mips/include/asm/futex.h ++++ b/arch/mips/include/asm/futex.h +@@ -83,18 +83,9 @@ + } + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/parisc/include/asm/futex.h ++++ b/arch/parisc/include/asm/futex.h +@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user + } + + 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; + u32 val; +- 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr))) +- return -EFAULT; + + pagefault_disable(); + +@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/powerpc/include/asm/futex.h ++++ b/arch/powerpc/include/asm/futex.h +@@ -31,18 +31,10 @@ + : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ + : "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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/s390/include/asm/futex.h ++++ b/arch/s390/include/asm/futex.h +@@ -21,17 +21,12 @@ + : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ + "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; + + load_kernel_asce(); +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; + + pagefault_disable(); + switch (op) { +@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/sh/include/asm/futex.h ++++ b/arch/sh/include/asm/futex.h +@@ -10,20 +10,11 @@ + /* XXX: UP variants, fix for SH-4A and SMP.. */ + #include <asm/futex-irq.h> + +-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 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(); + + switch (op) { +@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + } +--- a/arch/sparc/include/asm/futex_64.h ++++ b/arch/sparc/include/asm/futex_64.h +@@ -29,22 +29,14 @@ + : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ + : "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; + +- if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) +- return -EFAULT; + if (unlikely((((unsigned long) uaddr) & 0x3UL))) + return -EINVAL; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + pagefault_disable(); + + switch (op) { +@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/tile/include/asm/futex.h ++++ b/arch/tile/include/asm/futex.h +@@ -106,12 +106,9 @@ + lock = __atomic_hashed_lock((int __force *)uaddr) + #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; + + __futex_prolog(); +@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser + /* The 32-bit futex code makes this assumption, so validate it here. */ + 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(); + switch (op) { + case FUTEX_OP_SET: +@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = val; ++ + return ret; + } + +--- a/arch/x86/include/asm/futex.h ++++ b/arch/x86/include/asm/futex.h +@@ -41,20 +41,11 @@ + "+m" (*uaddr), "=&r" (tem) \ + : "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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/xtensa/include/asm/futex.h ++++ b/arch/xtensa/include/asm/futex.h +@@ -44,18 +44,10 @@ + : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \ + : "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; +- 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 + return -ENOSYS; +@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- 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); +- } ++ if (!ret) ++ *oval = oldval; + +- return -ENOSYS; ++ return ret; + } + + static inline int +--- a/include/asm-generic/futex.h ++++ b/include/asm-generic/futex.h +@@ -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 + * futex value with another constant. + * +@@ -25,18 +25,11 @@ + * <0 - On error + */ + 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; + u32 tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + preempt_disable(); + pagefault_disable(); + +@@ -74,17 +67,9 @@ out_pagefault_enable: + pagefault_enable(); + preempt_enable(); + +- if (ret == 0) { +- switch (cmp) { +- 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; +- } +- } ++ if (ret == 0) ++ *oval = oldval; ++ + return ret; + } + +@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + + #else + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1453,6 +1453,45 @@ out: + 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 + * to this virtual address: + + +Patches currently in stable-queue which might be from jslaby at suse.cz are + +queue-4.4/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch diff --git a/a/content_digest b/N3/content_digest index a9fcf82..534f81d 100644 --- a/a/content_digest +++ b/N3/content_digest @@ -1,49 +1,7 @@ - "From\0<gregkh@linuxfoundation.org>\0" - "Subject\0Patch \"futex: Remove duplicated code and fix undefined behaviour\" has been added to the 4.4-stable tree\0" + "From\0gregkh@linuxfoundation.org <gregkh@linuxfoundation.org>\0" + "Subject\0[OpenRISC] Patch \"futex: Remove duplicated code and fix undefined behaviour\" has been added to the 4.4-stable tree\0" "Date\0Thu, 17 May 2018 11:38:53 +0200\0" - "To\020170824073105.3901-1-jslaby@suse.cz" - arnd@arndb.de - ben.hutchings@codethink.co.uk - benh@kernel.crashing.org - catalin.marinas@arm.com - chris@zankel.net - cmetcalf@mellanox.com - dalias@libc.org - davem@davemloft.net - deller@gmx.de - dvhart@infradead.org - fenghua.yu@intel.com - gregkh@linuxfoundation.org - heiko.carstens@de.ibm.com - ink@jurassic.park.msu.ru - jcmvbkbc@gmail.com - jejb@parisc-linux.org - jonas@southpole.se - jslaby@suse.cz - linux-arm-kernel@lists.infradead.org - linux-mips@linux-mips.org - linux-snps-arc@lists.infradead.org - linux-xtensa@linux-xtensa.org - linuxppc-dev@lists.ozlabs.org - mattst88@gmail.com - monstr@monstr.eu - mpe@ellerman.id.au - openrisc@lists.librecores.org - paulus@samba.org - peterz@infradead.org - ralf@linux-mips.org - rkuo@codeaurora.org - rmk+kernel@armlinux.org.uk - rth@twiddle.net - schwidefsky@de.ibm.com - shorne@gmail.com - stefan.kristiansson@saunalahti.fi - tglx@linutronix.de - tony.luck@intel.com - vgupta@synopsys.com - will.deacon@arm.com - " ysato@users.sourceforge.jp\0" - "Cc\0<stable-commits@vger.kernel.org>\0" + "To\0openrisc@lists.librecores.org\0" "\00:1\0" "b\0" "\n" @@ -59,6 +17,1100 @@ "and it can be found in the queue-4.4 subdirectory.\n" "\n" "If you, or anyone else, feels it should not be added to the stable tree,\n" - please let <stable@vger.kernel.org> know about it. + "please let <stable@vger.kernel.org> know about it.\n" + "\n" + "\n" + "From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001\n" + "From: Jiri Slaby <jslaby@suse.cz>\n" + "Date: Thu, 24 Aug 2017 09:31:05 +0200\n" + "Subject: futex: Remove duplicated code and fix undefined behaviour\n" + "\n" + "From: Jiri Slaby <jslaby@suse.cz>\n" + "\n" + "commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream.\n" + "\n" + "There is code duplicated over all architecture's headers for\n" + "futex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr,\n" + "and comparison of the result.\n" + "\n" + "Remove this duplication and leave up to the arches only the needed\n" + "assembly which is now in arch_futex_atomic_op_inuser.\n" + "\n" + "This effectively distributes the Will Deacon's arm64 fix for undefined\n" + "behaviour reported by UBSAN to all architectures. The fix was done in\n" + "commit 5f16a046f8e1 (arm64: futex: Fix undefined behaviour with\n" + "FUTEX_OP_OPARG_SHIFT usage). Look there for an example dump.\n" + "\n" + "And as suggested by Thomas, check for negative oparg too, because it was\n" + "also reported to cause undefined behaviour report.\n" + "\n" + "Note that s390 removed access_ok check in d12a29703 (\"s390/uaccess:\n" + "remove pointless access_ok() checks\") as access_ok there returns true.\n" + "We introduce it back to the helper for the sake of simplicity (it gets\n" + "optimized away anyway).\n" + "\n" + "Signed-off-by: Jiri Slaby <jslaby@suse.cz>\n" + "Signed-off-by: Thomas Gleixner <tglx@linutronix.de>\n" + "Acked-by: Russell King <rmk+kernel@armlinux.org.uk>\n" + "Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)\n" + "Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> [s390]\n" + "Acked-by: Chris Metcalf <cmetcalf@mellanox.com> [for tile]\n" + "Reviewed-by: Darren Hart (VMware) <dvhart@infradead.org>\n" + "Reviewed-by: Will Deacon <will.deacon@arm.com> [core/arm64]\n" + "Cc: linux-mips at linux-mips.org\n" + "Cc: Rich Felker <dalias@libc.org>\n" + "Cc: linux-ia64 at vger.kernel.org\n" + "Cc: linux-sh at vger.kernel.org\n" + "Cc: peterz at infradead.org\n" + "Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>\n" + "Cc: Max Filippov <jcmvbkbc@gmail.com>\n" + "Cc: Paul Mackerras <paulus@samba.org>\n" + "Cc: sparclinux at vger.kernel.org\n" + "Cc: Jonas Bonn <jonas@southpole.se>\n" + "Cc: linux-s390 at vger.kernel.org\n" + "Cc: linux-arch at vger.kernel.org\n" + "Cc: Yoshinori Sato <ysato@users.sourceforge.jp>\n" + "Cc: linux-hexagon at vger.kernel.org\n" + "Cc: Helge Deller <deller@gmx.de>\n" + "Cc: \"James E.J. Bottomley\" <jejb@parisc-linux.org>\n" + "Cc: Catalin Marinas <catalin.marinas@arm.com>\n" + "Cc: Matt Turner <mattst88@gmail.com>\n" + "Cc: linux-snps-arc at lists.infradead.org\n" + "Cc: Fenghua Yu <fenghua.yu@intel.com>\n" + "Cc: Arnd Bergmann <arnd@arndb.de>\n" + "Cc: linux-xtensa at linux-xtensa.org\n" + "Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>\n" + "Cc: openrisc at lists.librecores.org\n" + "Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>\n" + "Cc: Stafford Horne <shorne@gmail.com>\n" + "Cc: linux-arm-kernel at lists.infradead.org\n" + "Cc: Richard Henderson <rth@twiddle.net>\n" + "Cc: Chris Zankel <chris@zankel.net>\n" + "Cc: Michal Simek <monstr@monstr.eu>\n" + "Cc: Tony Luck <tony.luck@intel.com>\n" + "Cc: linux-parisc at vger.kernel.org\n" + "Cc: Vineet Gupta <vgupta@synopsys.com>\n" + "Cc: Ralf Baechle <ralf@linux-mips.org>\n" + "Cc: Richard Kuo <rkuo@codeaurora.org>\n" + "Cc: linux-alpha at vger.kernel.org\n" + "Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>\n" + "Cc: linuxppc-dev at lists.ozlabs.org\n" + "Cc: \"David S. Miller\" <davem@davemloft.net>\n" + "Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby at suse.cz\n" + "Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>\n" + "Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>\n" + "\n" + "---\n" + " arch/alpha/include/asm/futex.h | 26 +++---------------\n" + " arch/arc/include/asm/futex.h | 40 +++-------------------------\n" + " arch/arm/include/asm/futex.h | 26 ++----------------\n" + " arch/arm64/include/asm/futex.h | 26 ++----------------\n" + " arch/frv/include/asm/futex.h | 3 +-\n" + " arch/frv/kernel/futex.c | 27 ++-----------------\n" + " arch/hexagon/include/asm/futex.h | 38 ++-------------------------\n" + " arch/ia64/include/asm/futex.h | 25 ++----------------\n" + " arch/microblaze/include/asm/futex.h | 38 ++-------------------------\n" + " arch/mips/include/asm/futex.h | 25 ++----------------\n" + " arch/parisc/include/asm/futex.h | 25 ++----------------\n" + " arch/powerpc/include/asm/futex.h | 26 +++---------------\n" + " arch/s390/include/asm/futex.h | 23 +++-------------\n" + " arch/sh/include/asm/futex.h | 26 ++----------------\n" + " arch/sparc/include/asm/futex_64.h | 26 +++---------------\n" + " arch/tile/include/asm/futex.h | 40 +++-------------------------\n" + " arch/x86/include/asm/futex.h | 40 +++-------------------------\n" + " arch/xtensa/include/asm/futex.h | 27 +++----------------\n" + " include/asm-generic/futex.h | 50 ++++++------------------------------\n" + " kernel/futex.c | 39 ++++++++++++++++++++++++++++\n" + " 20 files changed, 126 insertions(+), 470 deletions(-)\n" + "\n" + "--- a/arch/alpha/include/asm/futex.h\n" + "+++ b/arch/alpha/include/asm/futex.h\n" + "@@ -29,18 +29,10 @@\n" + " \t:\t\"r\" (uaddr), \"r\"(oparg)\t\t\t\t\\\n" + " \t:\t\"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arc/include/asm/futex.h\n" + "+++ b/arch/arc/include/asm/futex.h\n" + "@@ -73,20 +73,11 @@\n" + " \n" + " #endif\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " #ifndef CONFIG_ARC_HAS_LLSC\n" + " \tpreempt_disable();\t/* to guarantee atomic r-m-w of futex op */\n" + " #endif\n" + "@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser\n" + " \tpreempt_enable();\n" + " #endif\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arm/include/asm/futex.h\n" + "+++ b/arch/arm/include/asm/futex.h\n" + "@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,\n" + " #endif /* !SMP */\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " #ifndef CONFIG_SMP\n" + " \tpreempt_disable();\n" + " #endif\n" + "@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \tpreempt_enable();\n" + " #endif\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arm64/include/asm/futex.h\n" + "+++ b/arch/arm64/include/asm/futex.h\n" + "@@ -53,20 +53,10 @@\n" + " \t: \"memory\")\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (int)(encoded_op << 8) >> 20;\n" + "-\tint cmparg = (int)(encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1U << (oparg & 0x1f);\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/frv/include/asm/futex.h\n" + "+++ b/arch/frv/include/asm/futex.h\n" + "@@ -7,7 +7,8 @@\n" + " #include <asm/errno.h>\n" + " #include <asm/uaccess.h>\n" + " \n" + "-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);\n" + "+extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr);\n" + " \n" + " static inline int\n" + " futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,\n" + "--- a/arch/frv/kernel/futex.c\n" + "+++ b/arch/frv/kernel/futex.c\n" + "@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x\n" + " /*\n" + " * do the futex operations\n" + " */\n" + "-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS; break;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + " \treturn ret;\n" + " \n" + "-} /* end futex_atomic_op_inuser() */\n" + "+} /* end arch_futex_atomic_op_inuser() */\n" + "--- a/arch/hexagon/include/asm/futex.h\n" + "+++ b/arch/hexagon/include/asm/futex.h\n" + "@@ -31,18 +31,9 @@\n" + " \n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/ia64/include/asm/futex.h\n" + "+++ b/arch/ia64/include/asm/futex.h\n" + "@@ -45,18 +45,9 @@ do {\t\t\t\t\t\t\t\t\t\\\n" + " } while (0)\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/microblaze/include/asm/futex.h\n" + "+++ b/arch/microblaze/include/asm/futex.h\n" + "@@ -29,18 +29,9 @@\n" + " })\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/mips/include/asm/futex.h\n" + "+++ b/arch/mips/include/asm/futex.h\n" + "@@ -83,18 +83,9 @@\n" + " }\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/parisc/include/asm/futex.h\n" + "+++ b/arch/parisc/include/asm/futex.h\n" + "@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user\n" + " }\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + " \tunsigned long int flags;\n" + " \tu32 val;\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/powerpc/include/asm/futex.h\n" + "+++ b/arch/powerpc/include/asm/futex.h\n" + "@@ -31,18 +31,10 @@\n" + " \t: \"b\" (uaddr), \"i\" (-EFAULT), \"r\" (oparg) \\\n" + " \t: \"cr0\", \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/s390/include/asm/futex.h\n" + "+++ b/arch/s390/include/asm/futex.h\n" + "@@ -21,17 +21,12 @@\n" + " \t\t: \"0\" (-EFAULT), \"d\" (oparg), \"a\" (uaddr),\t\t\\\n" + " \t\t \"m\" (*uaddr) : \"cc\");\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, newval, ret;\n" + " \n" + " \tload_kernel_asce();\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + " \n" + " \tpagefault_disable();\n" + " \tswitch (op) {\n" + "@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser\n" + " \t}\n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/sh/include/asm/futex.h\n" + "+++ b/arch/sh/include/asm/futex.h\n" + "@@ -10,20 +10,11 @@\n" + " /* XXX: UP variants, fix for SH-4A and SMP.. */\n" + " #include <asm/futex-irq.h>\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + " \treturn ret;\n" + " }\n" + "--- a/arch/sparc/include/asm/futex_64.h\n" + "+++ b/arch/sparc/include/asm/futex_64.h\n" + "@@ -29,22 +29,14 @@\n" + " \t: \"r\" (uaddr), \"r\" (oparg), \"i\" (-EFAULT)\t\\\n" + " \t: \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tem;\n" + " \n" + "-\tif (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))\n" + "-\t\treturn -EFAULT;\n" + " \tif (unlikely((((unsigned long) uaddr) & 0x3UL)))\n" + " \t\treturn -EINVAL;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/tile/include/asm/futex.h\n" + "+++ b/arch/tile/include/asm/futex.h\n" + "@@ -106,12 +106,9 @@\n" + " \tlock = __atomic_hashed_lock((int __force *)uaddr)\n" + " #endif\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint uninitialized_var(val), ret;\n" + " \n" + " \t__futex_prolog();\n" + "@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser\n" + " \t/* The 32-bit futex code makes this assumption, so validate it here. */\n" + " \tBUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \tswitch (op) {\n" + " \tcase FUTEX_OP_SET:\n" + "@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser\n" + " \t}\n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (val == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (val != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (val < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (val >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (val <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (val > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = val;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/x86/include/asm/futex.h\n" + "+++ b/arch/x86/include/asm/futex.h\n" + "@@ -41,20 +41,11 @@\n" + " \t\t \"+m\" (*uaddr), \"=&r\" (tem)\t\t\\\n" + " \t\t : \"r\" (oparg), \"i\" (-EFAULT), \"1\" (0))\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tem;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/xtensa/include/asm/futex.h\n" + "+++ b/arch/xtensa/include/asm/futex.h\n" + "@@ -44,18 +44,10 @@\n" + " \t: \"r\" (uaddr), \"I\" (-EFAULT), \"r\" (oparg)\t\\\n" + " \t: \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " #if !XCHAL_HAVE_S32C1I\n" + " \treturn -ENOSYS;\n" + "@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (ret)\n" + "-\t\treturn ret;\n" + "-\n" + "-\tswitch (cmp) {\n" + "-\tcase FUTEX_OP_CMP_EQ: return (oldval == cmparg);\n" + "-\tcase FUTEX_OP_CMP_NE: return (oldval != cmparg);\n" + "-\tcase FUTEX_OP_CMP_LT: return (oldval < cmparg);\n" + "-\tcase FUTEX_OP_CMP_GE: return (oldval >= cmparg);\n" + "-\tcase FUTEX_OP_CMP_LE: return (oldval <= cmparg);\n" + "-\tcase FUTEX_OP_CMP_GT: return (oldval > cmparg);\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + "-\treturn -ENOSYS;\n" + "+\treturn ret;\n" + " }\n" + " \n" + " static inline int\n" + "--- a/include/asm-generic/futex.h\n" + "+++ b/include/asm-generic/futex.h\n" + "@@ -13,7 +13,7 @@\n" + " */\n" + " \n" + " /**\n" + "- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n" + "+ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n" + " *\t\t\t argument and comparison of the previous\n" + " *\t\t\t futex value with another constant.\n" + " *\n" + "@@ -25,18 +25,11 @@\n" + " * <0 - On error\n" + " */\n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval, ret;\n" + " \tu32 tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + " \tpreempt_disable();\n" + " \tpagefault_disable();\n" + " \n" + "@@ -74,17 +67,9 @@ out_pagefault_enable:\n" + " \tpagefault_enable();\n" + " \tpreempt_enable();\n" + " \n" + "-\tif (ret == 0) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (ret == 0)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,\n" + " \n" + " #else\n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/kernel/futex.c\n" + "+++ b/kernel/futex.c\n" + "@@ -1453,6 +1453,45 @@ out:\n" + " \treturn ret;\n" + " }\n" + " \n" + "+static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n" + "+{\n" + "+\tunsigned int op =\t (encoded_op & 0x70000000) >> 28;\n" + "+\tunsigned int cmp =\t (encoded_op & 0x0f000000) >> 24;\n" + "+\tint oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);\n" + "+\tint cmparg = sign_extend32(encoded_op & 0x00000fff, 12);\n" + "+\tint oldval, ret;\n" + "+\n" + "+\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {\n" + "+\t\tif (oparg < 0 || oparg > 31)\n" + "+\t\t\treturn -EINVAL;\n" + "+\t\toparg = 1 << oparg;\n" + "+\t}\n" + "+\n" + "+\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "+\t\treturn -EFAULT;\n" + "+\n" + "+\tret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);\n" + "+\tif (ret)\n" + "+\t\treturn ret;\n" + "+\n" + "+\tswitch (cmp) {\n" + "+\tcase FUTEX_OP_CMP_EQ:\n" + "+\t\treturn oldval == cmparg;\n" + "+\tcase FUTEX_OP_CMP_NE:\n" + "+\t\treturn oldval != cmparg;\n" + "+\tcase FUTEX_OP_CMP_LT:\n" + "+\t\treturn oldval < cmparg;\n" + "+\tcase FUTEX_OP_CMP_GE:\n" + "+\t\treturn oldval >= cmparg;\n" + "+\tcase FUTEX_OP_CMP_LE:\n" + "+\t\treturn oldval <= cmparg;\n" + "+\tcase FUTEX_OP_CMP_GT:\n" + "+\t\treturn oldval > cmparg;\n" + "+\tdefault:\n" + "+\t\treturn -ENOSYS;\n" + "+\t}\n" + "+}\n" + "+\n" + " /*\n" + " * Wake up all waiters hashed on the physical page that is mapped\n" + " * to this virtual address:\n" + "\n" + "\n" + "Patches currently in stable-queue which might be from jslaby at suse.cz are\n" + "\n" + queue-4.4/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch -f87e12fcc4b63fa4f725f8fcbd2ab6c4f98754ab10827b6719644b9c25712681 +183f9e5604cb62b909ab058c3e497493e97311be08cb3c5ec14619f64da5eb79
diff --git a/a/1.txt b/N4/1.txt index d6bf5c4..04da79a 100644 --- a/a/1.txt +++ b/N4/1.txt @@ -12,3 +12,1097 @@ and it can be found in the queue-4.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@vger.kernel.org> know about it. + + +>From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby <jslaby@suse.cz> +Date: Thu, 24 Aug 2017 09:31:05 +0200 +Subject: futex: Remove duplicated code and fix undefined behaviour + +From: Jiri Slaby <jslaby@suse.cz> + +commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream. + +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 +commit 5f16a046f8e1 (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 in d12a29703 ("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 +Cc: Ben Hutchings <ben.hutchings@codethink.co.uk> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + +--- + arch/alpha/include/asm/futex.h | 26 +++--------------- + arch/arc/include/asm/futex.h | 40 +++------------------------- + arch/arm/include/asm/futex.h | 26 ++---------------- + arch/arm64/include/asm/futex.h | 26 ++---------------- + arch/frv/include/asm/futex.h | 3 +- + arch/frv/kernel/futex.c | 27 ++----------------- + arch/hexagon/include/asm/futex.h | 38 ++------------------------- + arch/ia64/include/asm/futex.h | 25 ++---------------- + arch/microblaze/include/asm/futex.h | 38 ++------------------------- + arch/mips/include/asm/futex.h | 25 ++---------------- + arch/parisc/include/asm/futex.h | 25 ++---------------- + arch/powerpc/include/asm/futex.h | 26 +++--------------- + arch/s390/include/asm/futex.h | 23 +++------------- + arch/sh/include/asm/futex.h | 26 ++---------------- + arch/sparc/include/asm/futex_64.h | 26 +++--------------- + arch/tile/include/asm/futex.h | 40 +++------------------------- + arch/x86/include/asm/futex.h | 40 +++------------------------- + arch/xtensa/include/asm/futex.h | 27 +++---------------- + include/asm-generic/futex.h | 50 ++++++------------------------------ + kernel/futex.c | 39 ++++++++++++++++++++++++++++ + 20 files changed, 126 insertions(+), 470 deletions(-) + +--- a/arch/alpha/include/asm/futex.h ++++ b/arch/alpha/include/asm/futex.h +@@ -29,18 +29,10 @@ + : "r" (uaddr), "r"(oparg) \ + : "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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arc/include/asm/futex.h ++++ b/arch/arc/include/asm/futex.h +@@ -73,20 +73,11 @@ + + #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; + +- 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 + preempt_disable(); /* to guarantee atomic r-m-w of futex op */ + #endif +@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + #endif /* !SMP */ + + 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + #ifndef CONFIG_SMP + preempt_disable(); + #endif +@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm64/include/asm/futex.h ++++ b/arch/arm64/include/asm/futex.h +@@ -53,20 +53,10 @@ + : "memory") + + 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1U << (oparg & 0x1f); +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/frv/include/asm/futex.h ++++ b/arch/frv/include/asm/futex.h +@@ -7,7 +7,8 @@ + #include <asm/errno.h> + #include <asm/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 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +--- a/arch/frv/kernel/futex.c ++++ b/arch/frv/kernel/futex.c +@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x + /* + * 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + +-} /* end futex_atomic_op_inuser() */ ++} /* end arch_futex_atomic_op_inuser() */ +--- a/arch/hexagon/include/asm/futex.h ++++ b/arch/hexagon/include/asm/futex.h +@@ -31,18 +31,9 @@ + + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) +- return -EFAULT; + + pagefault_disable(); + +@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/ia64/include/asm/futex.h ++++ b/arch/ia64/include/asm/futex.h +@@ -45,18 +45,9 @@ do { \ + } while (0) + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/microblaze/include/asm/futex.h ++++ b/arch/microblaze/include/asm/futex.h +@@ -29,18 +29,9 @@ + }) + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/mips/include/asm/futex.h ++++ b/arch/mips/include/asm/futex.h +@@ -83,18 +83,9 @@ + } + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/parisc/include/asm/futex.h ++++ b/arch/parisc/include/asm/futex.h +@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user + } + + 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; + u32 val; +- 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr))) +- return -EFAULT; + + pagefault_disable(); + +@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/powerpc/include/asm/futex.h ++++ b/arch/powerpc/include/asm/futex.h +@@ -31,18 +31,10 @@ + : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ + : "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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/s390/include/asm/futex.h ++++ b/arch/s390/include/asm/futex.h +@@ -21,17 +21,12 @@ + : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ + "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; + + load_kernel_asce(); +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; + + pagefault_disable(); + switch (op) { +@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/sh/include/asm/futex.h ++++ b/arch/sh/include/asm/futex.h +@@ -10,20 +10,11 @@ + /* XXX: UP variants, fix for SH-4A and SMP.. */ + #include <asm/futex-irq.h> + +-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 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(); + + switch (op) { +@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + } +--- a/arch/sparc/include/asm/futex_64.h ++++ b/arch/sparc/include/asm/futex_64.h +@@ -29,22 +29,14 @@ + : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ + : "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; + +- if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) +- return -EFAULT; + if (unlikely((((unsigned long) uaddr) & 0x3UL))) + return -EINVAL; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + pagefault_disable(); + + switch (op) { +@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/tile/include/asm/futex.h ++++ b/arch/tile/include/asm/futex.h +@@ -106,12 +106,9 @@ + lock = __atomic_hashed_lock((int __force *)uaddr) + #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; + + __futex_prolog(); +@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser + /* The 32-bit futex code makes this assumption, so validate it here. */ + 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(); + switch (op) { + case FUTEX_OP_SET: +@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = val; ++ + return ret; + } + +--- a/arch/x86/include/asm/futex.h ++++ b/arch/x86/include/asm/futex.h +@@ -41,20 +41,11 @@ + "+m" (*uaddr), "=&r" (tem) \ + : "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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/xtensa/include/asm/futex.h ++++ b/arch/xtensa/include/asm/futex.h +@@ -44,18 +44,10 @@ + : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \ + : "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; +- 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 + return -ENOSYS; +@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- 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); +- } ++ if (!ret) ++ *oval = oldval; + +- return -ENOSYS; ++ return ret; + } + + static inline int +--- a/include/asm-generic/futex.h ++++ b/include/asm-generic/futex.h +@@ -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 + * futex value with another constant. + * +@@ -25,18 +25,11 @@ + * <0 - On error + */ + 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; + u32 tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + preempt_disable(); + pagefault_disable(); + +@@ -74,17 +67,9 @@ out_pagefault_enable: + pagefault_enable(); + preempt_enable(); + +- if (ret == 0) { +- switch (cmp) { +- 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; +- } +- } ++ if (ret == 0) ++ *oval = oldval; ++ + return ret; + } + +@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + + #else + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1453,6 +1453,45 @@ out: + 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 + * to this virtual address: + + +Patches currently in stable-queue which might be from jslaby@suse.cz are + +queue-4.4/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch diff --git a/a/content_digest b/N4/content_digest index a9fcf82..408ae83 100644 --- a/a/content_digest +++ b/N4/content_digest @@ -59,6 +59,1100 @@ "and it can be found in the queue-4.4 subdirectory.\n" "\n" "If you, or anyone else, feels it should not be added to the stable tree,\n" - please let <stable@vger.kernel.org> know about it. + "please let <stable@vger.kernel.org> know about it.\n" + "\n" + "\n" + ">From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001\n" + "From: Jiri Slaby <jslaby@suse.cz>\n" + "Date: Thu, 24 Aug 2017 09:31:05 +0200\n" + "Subject: futex: Remove duplicated code and fix undefined behaviour\n" + "\n" + "From: Jiri Slaby <jslaby@suse.cz>\n" + "\n" + "commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream.\n" + "\n" + "There is code duplicated over all architecture's headers for\n" + "futex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr,\n" + "and comparison of the result.\n" + "\n" + "Remove this duplication and leave up to the arches only the needed\n" + "assembly which is now in arch_futex_atomic_op_inuser.\n" + "\n" + "This effectively distributes the Will Deacon's arm64 fix for undefined\n" + "behaviour reported by UBSAN to all architectures. The fix was done in\n" + "commit 5f16a046f8e1 (arm64: futex: Fix undefined behaviour with\n" + "FUTEX_OP_OPARG_SHIFT usage). Look there for an example dump.\n" + "\n" + "And as suggested by Thomas, check for negative oparg too, because it was\n" + "also reported to cause undefined behaviour report.\n" + "\n" + "Note that s390 removed access_ok check in d12a29703 (\"s390/uaccess:\n" + "remove pointless access_ok() checks\") as access_ok there returns true.\n" + "We introduce it back to the helper for the sake of simplicity (it gets\n" + "optimized away anyway).\n" + "\n" + "Signed-off-by: Jiri Slaby <jslaby@suse.cz>\n" + "Signed-off-by: Thomas Gleixner <tglx@linutronix.de>\n" + "Acked-by: Russell King <rmk+kernel@armlinux.org.uk>\n" + "Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)\n" + "Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> [s390]\n" + "Acked-by: Chris Metcalf <cmetcalf@mellanox.com> [for tile]\n" + "Reviewed-by: Darren Hart (VMware) <dvhart@infradead.org>\n" + "Reviewed-by: Will Deacon <will.deacon@arm.com> [core/arm64]\n" + "Cc: linux-mips@linux-mips.org\n" + "Cc: Rich Felker <dalias@libc.org>\n" + "Cc: linux-ia64@vger.kernel.org\n" + "Cc: linux-sh@vger.kernel.org\n" + "Cc: peterz@infradead.org\n" + "Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>\n" + "Cc: Max Filippov <jcmvbkbc@gmail.com>\n" + "Cc: Paul Mackerras <paulus@samba.org>\n" + "Cc: sparclinux@vger.kernel.org\n" + "Cc: Jonas Bonn <jonas@southpole.se>\n" + "Cc: linux-s390@vger.kernel.org\n" + "Cc: linux-arch@vger.kernel.org\n" + "Cc: Yoshinori Sato <ysato@users.sourceforge.jp>\n" + "Cc: linux-hexagon@vger.kernel.org\n" + "Cc: Helge Deller <deller@gmx.de>\n" + "Cc: \"James E.J. Bottomley\" <jejb@parisc-linux.org>\n" + "Cc: Catalin Marinas <catalin.marinas@arm.com>\n" + "Cc: Matt Turner <mattst88@gmail.com>\n" + "Cc: linux-snps-arc@lists.infradead.org\n" + "Cc: Fenghua Yu <fenghua.yu@intel.com>\n" + "Cc: Arnd Bergmann <arnd@arndb.de>\n" + "Cc: linux-xtensa@linux-xtensa.org\n" + "Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>\n" + "Cc: openrisc@lists.librecores.org\n" + "Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>\n" + "Cc: Stafford Horne <shorne@gmail.com>\n" + "Cc: linux-arm-kernel@lists.infradead.org\n" + "Cc: Richard Henderson <rth@twiddle.net>\n" + "Cc: Chris Zankel <chris@zankel.net>\n" + "Cc: Michal Simek <monstr@monstr.eu>\n" + "Cc: Tony Luck <tony.luck@intel.com>\n" + "Cc: linux-parisc@vger.kernel.org\n" + "Cc: Vineet Gupta <vgupta@synopsys.com>\n" + "Cc: Ralf Baechle <ralf@linux-mips.org>\n" + "Cc: Richard Kuo <rkuo@codeaurora.org>\n" + "Cc: linux-alpha@vger.kernel.org\n" + "Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>\n" + "Cc: linuxppc-dev@lists.ozlabs.org\n" + "Cc: \"David S. Miller\" <davem@davemloft.net>\n" + "Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby@suse.cz\n" + "Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>\n" + "Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>\n" + "\n" + "---\n" + " arch/alpha/include/asm/futex.h | 26 +++---------------\n" + " arch/arc/include/asm/futex.h | 40 +++-------------------------\n" + " arch/arm/include/asm/futex.h | 26 ++----------------\n" + " arch/arm64/include/asm/futex.h | 26 ++----------------\n" + " arch/frv/include/asm/futex.h | 3 +-\n" + " arch/frv/kernel/futex.c | 27 ++-----------------\n" + " arch/hexagon/include/asm/futex.h | 38 ++-------------------------\n" + " arch/ia64/include/asm/futex.h | 25 ++----------------\n" + " arch/microblaze/include/asm/futex.h | 38 ++-------------------------\n" + " arch/mips/include/asm/futex.h | 25 ++----------------\n" + " arch/parisc/include/asm/futex.h | 25 ++----------------\n" + " arch/powerpc/include/asm/futex.h | 26 +++---------------\n" + " arch/s390/include/asm/futex.h | 23 +++-------------\n" + " arch/sh/include/asm/futex.h | 26 ++----------------\n" + " arch/sparc/include/asm/futex_64.h | 26 +++---------------\n" + " arch/tile/include/asm/futex.h | 40 +++-------------------------\n" + " arch/x86/include/asm/futex.h | 40 +++-------------------------\n" + " arch/xtensa/include/asm/futex.h | 27 +++----------------\n" + " include/asm-generic/futex.h | 50 ++++++------------------------------\n" + " kernel/futex.c | 39 ++++++++++++++++++++++++++++\n" + " 20 files changed, 126 insertions(+), 470 deletions(-)\n" + "\n" + "--- a/arch/alpha/include/asm/futex.h\n" + "+++ b/arch/alpha/include/asm/futex.h\n" + "@@ -29,18 +29,10 @@\n" + " \t:\t\"r\" (uaddr), \"r\"(oparg)\t\t\t\t\\\n" + " \t:\t\"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arc/include/asm/futex.h\n" + "+++ b/arch/arc/include/asm/futex.h\n" + "@@ -73,20 +73,11 @@\n" + " \n" + " #endif\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " #ifndef CONFIG_ARC_HAS_LLSC\n" + " \tpreempt_disable();\t/* to guarantee atomic r-m-w of futex op */\n" + " #endif\n" + "@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser\n" + " \tpreempt_enable();\n" + " #endif\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arm/include/asm/futex.h\n" + "+++ b/arch/arm/include/asm/futex.h\n" + "@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,\n" + " #endif /* !SMP */\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " #ifndef CONFIG_SMP\n" + " \tpreempt_disable();\n" + " #endif\n" + "@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \tpreempt_enable();\n" + " #endif\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arm64/include/asm/futex.h\n" + "+++ b/arch/arm64/include/asm/futex.h\n" + "@@ -53,20 +53,10 @@\n" + " \t: \"memory\")\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (int)(encoded_op << 8) >> 20;\n" + "-\tint cmparg = (int)(encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1U << (oparg & 0x1f);\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/frv/include/asm/futex.h\n" + "+++ b/arch/frv/include/asm/futex.h\n" + "@@ -7,7 +7,8 @@\n" + " #include <asm/errno.h>\n" + " #include <asm/uaccess.h>\n" + " \n" + "-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);\n" + "+extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr);\n" + " \n" + " static inline int\n" + " futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,\n" + "--- a/arch/frv/kernel/futex.c\n" + "+++ b/arch/frv/kernel/futex.c\n" + "@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x\n" + " /*\n" + " * do the futex operations\n" + " */\n" + "-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS; break;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + " \treturn ret;\n" + " \n" + "-} /* end futex_atomic_op_inuser() */\n" + "+} /* end arch_futex_atomic_op_inuser() */\n" + "--- a/arch/hexagon/include/asm/futex.h\n" + "+++ b/arch/hexagon/include/asm/futex.h\n" + "@@ -31,18 +31,9 @@\n" + " \n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/ia64/include/asm/futex.h\n" + "+++ b/arch/ia64/include/asm/futex.h\n" + "@@ -45,18 +45,9 @@ do {\t\t\t\t\t\t\t\t\t\\\n" + " } while (0)\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/microblaze/include/asm/futex.h\n" + "+++ b/arch/microblaze/include/asm/futex.h\n" + "@@ -29,18 +29,9 @@\n" + " })\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/mips/include/asm/futex.h\n" + "+++ b/arch/mips/include/asm/futex.h\n" + "@@ -83,18 +83,9 @@\n" + " }\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/parisc/include/asm/futex.h\n" + "+++ b/arch/parisc/include/asm/futex.h\n" + "@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user\n" + " }\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + " \tunsigned long int flags;\n" + " \tu32 val;\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/powerpc/include/asm/futex.h\n" + "+++ b/arch/powerpc/include/asm/futex.h\n" + "@@ -31,18 +31,10 @@\n" + " \t: \"b\" (uaddr), \"i\" (-EFAULT), \"r\" (oparg) \\\n" + " \t: \"cr0\", \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/s390/include/asm/futex.h\n" + "+++ b/arch/s390/include/asm/futex.h\n" + "@@ -21,17 +21,12 @@\n" + " \t\t: \"0\" (-EFAULT), \"d\" (oparg), \"a\" (uaddr),\t\t\\\n" + " \t\t \"m\" (*uaddr) : \"cc\");\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, newval, ret;\n" + " \n" + " \tload_kernel_asce();\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + " \n" + " \tpagefault_disable();\n" + " \tswitch (op) {\n" + "@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser\n" + " \t}\n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/sh/include/asm/futex.h\n" + "+++ b/arch/sh/include/asm/futex.h\n" + "@@ -10,20 +10,11 @@\n" + " /* XXX: UP variants, fix for SH-4A and SMP.. */\n" + " #include <asm/futex-irq.h>\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + " \treturn ret;\n" + " }\n" + "--- a/arch/sparc/include/asm/futex_64.h\n" + "+++ b/arch/sparc/include/asm/futex_64.h\n" + "@@ -29,22 +29,14 @@\n" + " \t: \"r\" (uaddr), \"r\" (oparg), \"i\" (-EFAULT)\t\\\n" + " \t: \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tem;\n" + " \n" + "-\tif (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))\n" + "-\t\treturn -EFAULT;\n" + " \tif (unlikely((((unsigned long) uaddr) & 0x3UL)))\n" + " \t\treturn -EINVAL;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/tile/include/asm/futex.h\n" + "+++ b/arch/tile/include/asm/futex.h\n" + "@@ -106,12 +106,9 @@\n" + " \tlock = __atomic_hashed_lock((int __force *)uaddr)\n" + " #endif\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint uninitialized_var(val), ret;\n" + " \n" + " \t__futex_prolog();\n" + "@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser\n" + " \t/* The 32-bit futex code makes this assumption, so validate it here. */\n" + " \tBUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \tswitch (op) {\n" + " \tcase FUTEX_OP_SET:\n" + "@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser\n" + " \t}\n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (val == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (val != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (val < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (val >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (val <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (val > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = val;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/x86/include/asm/futex.h\n" + "+++ b/arch/x86/include/asm/futex.h\n" + "@@ -41,20 +41,11 @@\n" + " \t\t \"+m\" (*uaddr), \"=&r\" (tem)\t\t\\\n" + " \t\t : \"r\" (oparg), \"i\" (-EFAULT), \"1\" (0))\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tem;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/xtensa/include/asm/futex.h\n" + "+++ b/arch/xtensa/include/asm/futex.h\n" + "@@ -44,18 +44,10 @@\n" + " \t: \"r\" (uaddr), \"I\" (-EFAULT), \"r\" (oparg)\t\\\n" + " \t: \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " #if !XCHAL_HAVE_S32C1I\n" + " \treturn -ENOSYS;\n" + "@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (ret)\n" + "-\t\treturn ret;\n" + "-\n" + "-\tswitch (cmp) {\n" + "-\tcase FUTEX_OP_CMP_EQ: return (oldval == cmparg);\n" + "-\tcase FUTEX_OP_CMP_NE: return (oldval != cmparg);\n" + "-\tcase FUTEX_OP_CMP_LT: return (oldval < cmparg);\n" + "-\tcase FUTEX_OP_CMP_GE: return (oldval >= cmparg);\n" + "-\tcase FUTEX_OP_CMP_LE: return (oldval <= cmparg);\n" + "-\tcase FUTEX_OP_CMP_GT: return (oldval > cmparg);\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + "-\treturn -ENOSYS;\n" + "+\treturn ret;\n" + " }\n" + " \n" + " static inline int\n" + "--- a/include/asm-generic/futex.h\n" + "+++ b/include/asm-generic/futex.h\n" + "@@ -13,7 +13,7 @@\n" + " */\n" + " \n" + " /**\n" + "- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n" + "+ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n" + " *\t\t\t argument and comparison of the previous\n" + " *\t\t\t futex value with another constant.\n" + " *\n" + "@@ -25,18 +25,11 @@\n" + " * <0 - On error\n" + " */\n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval, ret;\n" + " \tu32 tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + " \tpreempt_disable();\n" + " \tpagefault_disable();\n" + " \n" + "@@ -74,17 +67,9 @@ out_pagefault_enable:\n" + " \tpagefault_enable();\n" + " \tpreempt_enable();\n" + " \n" + "-\tif (ret == 0) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (ret == 0)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,\n" + " \n" + " #else\n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/kernel/futex.c\n" + "+++ b/kernel/futex.c\n" + "@@ -1453,6 +1453,45 @@ out:\n" + " \treturn ret;\n" + " }\n" + " \n" + "+static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n" + "+{\n" + "+\tunsigned int op =\t (encoded_op & 0x70000000) >> 28;\n" + "+\tunsigned int cmp =\t (encoded_op & 0x0f000000) >> 24;\n" + "+\tint oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);\n" + "+\tint cmparg = sign_extend32(encoded_op & 0x00000fff, 12);\n" + "+\tint oldval, ret;\n" + "+\n" + "+\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {\n" + "+\t\tif (oparg < 0 || oparg > 31)\n" + "+\t\t\treturn -EINVAL;\n" + "+\t\toparg = 1 << oparg;\n" + "+\t}\n" + "+\n" + "+\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "+\t\treturn -EFAULT;\n" + "+\n" + "+\tret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);\n" + "+\tif (ret)\n" + "+\t\treturn ret;\n" + "+\n" + "+\tswitch (cmp) {\n" + "+\tcase FUTEX_OP_CMP_EQ:\n" + "+\t\treturn oldval == cmparg;\n" + "+\tcase FUTEX_OP_CMP_NE:\n" + "+\t\treturn oldval != cmparg;\n" + "+\tcase FUTEX_OP_CMP_LT:\n" + "+\t\treturn oldval < cmparg;\n" + "+\tcase FUTEX_OP_CMP_GE:\n" + "+\t\treturn oldval >= cmparg;\n" + "+\tcase FUTEX_OP_CMP_LE:\n" + "+\t\treturn oldval <= cmparg;\n" + "+\tcase FUTEX_OP_CMP_GT:\n" + "+\t\treturn oldval > cmparg;\n" + "+\tdefault:\n" + "+\t\treturn -ENOSYS;\n" + "+\t}\n" + "+}\n" + "+\n" + " /*\n" + " * Wake up all waiters hashed on the physical page that is mapped\n" + " * to this virtual address:\n" + "\n" + "\n" + "Patches currently in stable-queue which might be from jslaby@suse.cz are\n" + "\n" + queue-4.4/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch -f87e12fcc4b63fa4f725f8fcbd2ab6c4f98754ab10827b6719644b9c25712681 +4ad86114352f5c4cb60a8ab9ab8b4a8235aca5445b6d43271ffcc1d50e21bca3
diff --git a/a/1.txt b/N5/1.txt index d6bf5c4..d923aa5 100644 --- a/a/1.txt +++ b/N5/1.txt @@ -12,3 +12,1097 @@ and it can be found in the queue-4.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@vger.kernel.org> know about it. + + +>From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby <jslaby@suse.cz> +Date: Thu, 24 Aug 2017 09:31:05 +0200 +Subject: futex: Remove duplicated code and fix undefined behaviour + +From: Jiri Slaby <jslaby@suse.cz> + +commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream. + +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 +commit 5f16a046f8e1 (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 in d12a29703 ("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 at linux-mips.org +Cc: Rich Felker <dalias@libc.org> +Cc: linux-ia64 at vger.kernel.org +Cc: linux-sh at vger.kernel.org +Cc: peterz at infradead.org +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Max Filippov <jcmvbkbc@gmail.com> +Cc: Paul Mackerras <paulus@samba.org> +Cc: sparclinux at vger.kernel.org +Cc: Jonas Bonn <jonas@southpole.se> +Cc: linux-s390 at vger.kernel.org +Cc: linux-arch at vger.kernel.org +Cc: Yoshinori Sato <ysato@users.sourceforge.jp> +Cc: linux-hexagon at 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 at lists.infradead.org +Cc: Fenghua Yu <fenghua.yu@intel.com> +Cc: Arnd Bergmann <arnd@arndb.de> +Cc: linux-xtensa at linux-xtensa.org +Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> +Cc: openrisc at lists.librecores.org +Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> +Cc: Stafford Horne <shorne@gmail.com> +Cc: linux-arm-kernel at 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 at 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 at vger.kernel.org +Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> +Cc: linuxppc-dev at lists.ozlabs.org +Cc: "David S. Miller" <davem@davemloft.net> +Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby at suse.cz +Cc: Ben Hutchings <ben.hutchings@codethink.co.uk> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + +--- + arch/alpha/include/asm/futex.h | 26 +++--------------- + arch/arc/include/asm/futex.h | 40 +++------------------------- + arch/arm/include/asm/futex.h | 26 ++---------------- + arch/arm64/include/asm/futex.h | 26 ++---------------- + arch/frv/include/asm/futex.h | 3 +- + arch/frv/kernel/futex.c | 27 ++----------------- + arch/hexagon/include/asm/futex.h | 38 ++------------------------- + arch/ia64/include/asm/futex.h | 25 ++---------------- + arch/microblaze/include/asm/futex.h | 38 ++------------------------- + arch/mips/include/asm/futex.h | 25 ++---------------- + arch/parisc/include/asm/futex.h | 25 ++---------------- + arch/powerpc/include/asm/futex.h | 26 +++--------------- + arch/s390/include/asm/futex.h | 23 +++------------- + arch/sh/include/asm/futex.h | 26 ++---------------- + arch/sparc/include/asm/futex_64.h | 26 +++--------------- + arch/tile/include/asm/futex.h | 40 +++------------------------- + arch/x86/include/asm/futex.h | 40 +++------------------------- + arch/xtensa/include/asm/futex.h | 27 +++---------------- + include/asm-generic/futex.h | 50 ++++++------------------------------ + kernel/futex.c | 39 ++++++++++++++++++++++++++++ + 20 files changed, 126 insertions(+), 470 deletions(-) + +--- a/arch/alpha/include/asm/futex.h ++++ b/arch/alpha/include/asm/futex.h +@@ -29,18 +29,10 @@ + : "r" (uaddr), "r"(oparg) \ + : "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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arc/include/asm/futex.h ++++ b/arch/arc/include/asm/futex.h +@@ -73,20 +73,11 @@ + + #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; + +- 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 + preempt_disable(); /* to guarantee atomic r-m-w of futex op */ + #endif +@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + #endif /* !SMP */ + + 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + #ifndef CONFIG_SMP + preempt_disable(); + #endif +@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm64/include/asm/futex.h ++++ b/arch/arm64/include/asm/futex.h +@@ -53,20 +53,10 @@ + : "memory") + + 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1U << (oparg & 0x1f); +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/frv/include/asm/futex.h ++++ b/arch/frv/include/asm/futex.h +@@ -7,7 +7,8 @@ + #include <asm/errno.h> + #include <asm/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 + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +--- a/arch/frv/kernel/futex.c ++++ b/arch/frv/kernel/futex.c +@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x + /* + * 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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + +-} /* end futex_atomic_op_inuser() */ ++} /* end arch_futex_atomic_op_inuser() */ +--- a/arch/hexagon/include/asm/futex.h ++++ b/arch/hexagon/include/asm/futex.h +@@ -31,18 +31,9 @@ + + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) +- return -EFAULT; + + pagefault_disable(); + +@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/ia64/include/asm/futex.h ++++ b/arch/ia64/include/asm/futex.h +@@ -45,18 +45,9 @@ do { \ + } while (0) + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/microblaze/include/asm/futex.h ++++ b/arch/microblaze/include/asm/futex.h +@@ -29,18 +29,9 @@ + }) + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/mips/include/asm/futex.h ++++ b/arch/mips/include/asm/futex.h +@@ -83,18 +83,9 @@ + } + + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/parisc/include/asm/futex.h ++++ b/arch/parisc/include/asm/futex.h +@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user + } + + 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; + u32 val; +- 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr))) +- return -EFAULT; + + pagefault_disable(); + +@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/powerpc/include/asm/futex.h ++++ b/arch/powerpc/include/asm/futex.h +@@ -31,18 +31,10 @@ + : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ + : "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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/s390/include/asm/futex.h ++++ b/arch/s390/include/asm/futex.h +@@ -21,17 +21,12 @@ + : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ + "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; + + load_kernel_asce(); +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; + + pagefault_disable(); + switch (op) { +@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/sh/include/asm/futex.h ++++ b/arch/sh/include/asm/futex.h +@@ -10,20 +10,11 @@ + /* XXX: UP variants, fix for SH-4A and SMP.. */ + #include <asm/futex-irq.h> + +-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 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(); + + switch (op) { +@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + } +--- a/arch/sparc/include/asm/futex_64.h ++++ b/arch/sparc/include/asm/futex_64.h +@@ -29,22 +29,14 @@ + : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ + : "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; + +- if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) +- return -EFAULT; + if (unlikely((((unsigned long) uaddr) & 0x3UL))) + return -EINVAL; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + pagefault_disable(); + + switch (op) { +@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/tile/include/asm/futex.h ++++ b/arch/tile/include/asm/futex.h +@@ -106,12 +106,9 @@ + lock = __atomic_hashed_lock((int __force *)uaddr) + #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; + + __futex_prolog(); +@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser + /* The 32-bit futex code makes this assumption, so validate it here. */ + 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(); + switch (op) { + case FUTEX_OP_SET: +@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = val; ++ + return ret; + } + +--- a/arch/x86/include/asm/futex.h ++++ b/arch/x86/include/asm/futex.h +@@ -41,20 +41,11 @@ + "+m" (*uaddr), "=&r" (tem) \ + : "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; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/xtensa/include/asm/futex.h ++++ b/arch/xtensa/include/asm/futex.h +@@ -44,18 +44,10 @@ + : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \ + : "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; +- 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 + return -ENOSYS; +@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- 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); +- } ++ if (!ret) ++ *oval = oldval; + +- return -ENOSYS; ++ return ret; + } + + static inline int +--- a/include/asm-generic/futex.h ++++ b/include/asm-generic/futex.h +@@ -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 + * futex value with another constant. + * +@@ -25,18 +25,11 @@ + * <0 - On error + */ + 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; + u32 tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + preempt_disable(); + pagefault_disable(); + +@@ -74,17 +67,9 @@ out_pagefault_enable: + pagefault_enable(); + preempt_enable(); + +- if (ret == 0) { +- switch (cmp) { +- 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; +- } +- } ++ if (ret == 0) ++ *oval = oldval; ++ + return ret; + } + +@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + + #else + 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; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- 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; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1453,6 +1453,45 @@ out: + 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 + * to this virtual address: + + +Patches currently in stable-queue which might be from jslaby at suse.cz are + +queue-4.4/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch diff --git a/a/content_digest b/N5/content_digest index a9fcf82..be6948f 100644 --- a/a/content_digest +++ b/N5/content_digest @@ -1,49 +1,7 @@ - "From\0<gregkh@linuxfoundation.org>\0" + "From\0gregkh@linuxfoundation.org (gregkh at linuxfoundation.org)\0" "Subject\0Patch \"futex: Remove duplicated code and fix undefined behaviour\" has been added to the 4.4-stable tree\0" "Date\0Thu, 17 May 2018 11:38:53 +0200\0" - "To\020170824073105.3901-1-jslaby@suse.cz" - arnd@arndb.de - ben.hutchings@codethink.co.uk - benh@kernel.crashing.org - catalin.marinas@arm.com - chris@zankel.net - cmetcalf@mellanox.com - dalias@libc.org - davem@davemloft.net - deller@gmx.de - dvhart@infradead.org - fenghua.yu@intel.com - gregkh@linuxfoundation.org - heiko.carstens@de.ibm.com - ink@jurassic.park.msu.ru - jcmvbkbc@gmail.com - jejb@parisc-linux.org - jonas@southpole.se - jslaby@suse.cz - linux-arm-kernel@lists.infradead.org - linux-mips@linux-mips.org - linux-snps-arc@lists.infradead.org - linux-xtensa@linux-xtensa.org - linuxppc-dev@lists.ozlabs.org - mattst88@gmail.com - monstr@monstr.eu - mpe@ellerman.id.au - openrisc@lists.librecores.org - paulus@samba.org - peterz@infradead.org - ralf@linux-mips.org - rkuo@codeaurora.org - rmk+kernel@armlinux.org.uk - rth@twiddle.net - schwidefsky@de.ibm.com - shorne@gmail.com - stefan.kristiansson@saunalahti.fi - tglx@linutronix.de - tony.luck@intel.com - vgupta@synopsys.com - will.deacon@arm.com - " ysato@users.sourceforge.jp\0" - "Cc\0<stable-commits@vger.kernel.org>\0" + "To\0linux-arm-kernel@lists.infradead.org\0" "\00:1\0" "b\0" "\n" @@ -59,6 +17,1100 @@ "and it can be found in the queue-4.4 subdirectory.\n" "\n" "If you, or anyone else, feels it should not be added to the stable tree,\n" - please let <stable@vger.kernel.org> know about it. + "please let <stable@vger.kernel.org> know about it.\n" + "\n" + "\n" + ">From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001\n" + "From: Jiri Slaby <jslaby@suse.cz>\n" + "Date: Thu, 24 Aug 2017 09:31:05 +0200\n" + "Subject: futex: Remove duplicated code and fix undefined behaviour\n" + "\n" + "From: Jiri Slaby <jslaby@suse.cz>\n" + "\n" + "commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream.\n" + "\n" + "There is code duplicated over all architecture's headers for\n" + "futex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr,\n" + "and comparison of the result.\n" + "\n" + "Remove this duplication and leave up to the arches only the needed\n" + "assembly which is now in arch_futex_atomic_op_inuser.\n" + "\n" + "This effectively distributes the Will Deacon's arm64 fix for undefined\n" + "behaviour reported by UBSAN to all architectures. The fix was done in\n" + "commit 5f16a046f8e1 (arm64: futex: Fix undefined behaviour with\n" + "FUTEX_OP_OPARG_SHIFT usage). Look there for an example dump.\n" + "\n" + "And as suggested by Thomas, check for negative oparg too, because it was\n" + "also reported to cause undefined behaviour report.\n" + "\n" + "Note that s390 removed access_ok check in d12a29703 (\"s390/uaccess:\n" + "remove pointless access_ok() checks\") as access_ok there returns true.\n" + "We introduce it back to the helper for the sake of simplicity (it gets\n" + "optimized away anyway).\n" + "\n" + "Signed-off-by: Jiri Slaby <jslaby@suse.cz>\n" + "Signed-off-by: Thomas Gleixner <tglx@linutronix.de>\n" + "Acked-by: Russell King <rmk+kernel@armlinux.org.uk>\n" + "Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)\n" + "Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> [s390]\n" + "Acked-by: Chris Metcalf <cmetcalf@mellanox.com> [for tile]\n" + "Reviewed-by: Darren Hart (VMware) <dvhart@infradead.org>\n" + "Reviewed-by: Will Deacon <will.deacon@arm.com> [core/arm64]\n" + "Cc: linux-mips at linux-mips.org\n" + "Cc: Rich Felker <dalias@libc.org>\n" + "Cc: linux-ia64 at vger.kernel.org\n" + "Cc: linux-sh at vger.kernel.org\n" + "Cc: peterz at infradead.org\n" + "Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>\n" + "Cc: Max Filippov <jcmvbkbc@gmail.com>\n" + "Cc: Paul Mackerras <paulus@samba.org>\n" + "Cc: sparclinux at vger.kernel.org\n" + "Cc: Jonas Bonn <jonas@southpole.se>\n" + "Cc: linux-s390 at vger.kernel.org\n" + "Cc: linux-arch at vger.kernel.org\n" + "Cc: Yoshinori Sato <ysato@users.sourceforge.jp>\n" + "Cc: linux-hexagon at vger.kernel.org\n" + "Cc: Helge Deller <deller@gmx.de>\n" + "Cc: \"James E.J. Bottomley\" <jejb@parisc-linux.org>\n" + "Cc: Catalin Marinas <catalin.marinas@arm.com>\n" + "Cc: Matt Turner <mattst88@gmail.com>\n" + "Cc: linux-snps-arc at lists.infradead.org\n" + "Cc: Fenghua Yu <fenghua.yu@intel.com>\n" + "Cc: Arnd Bergmann <arnd@arndb.de>\n" + "Cc: linux-xtensa at linux-xtensa.org\n" + "Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>\n" + "Cc: openrisc at lists.librecores.org\n" + "Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>\n" + "Cc: Stafford Horne <shorne@gmail.com>\n" + "Cc: linux-arm-kernel at lists.infradead.org\n" + "Cc: Richard Henderson <rth@twiddle.net>\n" + "Cc: Chris Zankel <chris@zankel.net>\n" + "Cc: Michal Simek <monstr@monstr.eu>\n" + "Cc: Tony Luck <tony.luck@intel.com>\n" + "Cc: linux-parisc at vger.kernel.org\n" + "Cc: Vineet Gupta <vgupta@synopsys.com>\n" + "Cc: Ralf Baechle <ralf@linux-mips.org>\n" + "Cc: Richard Kuo <rkuo@codeaurora.org>\n" + "Cc: linux-alpha at vger.kernel.org\n" + "Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>\n" + "Cc: linuxppc-dev at lists.ozlabs.org\n" + "Cc: \"David S. Miller\" <davem@davemloft.net>\n" + "Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby at suse.cz\n" + "Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>\n" + "Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>\n" + "\n" + "---\n" + " arch/alpha/include/asm/futex.h | 26 +++---------------\n" + " arch/arc/include/asm/futex.h | 40 +++-------------------------\n" + " arch/arm/include/asm/futex.h | 26 ++----------------\n" + " arch/arm64/include/asm/futex.h | 26 ++----------------\n" + " arch/frv/include/asm/futex.h | 3 +-\n" + " arch/frv/kernel/futex.c | 27 ++-----------------\n" + " arch/hexagon/include/asm/futex.h | 38 ++-------------------------\n" + " arch/ia64/include/asm/futex.h | 25 ++----------------\n" + " arch/microblaze/include/asm/futex.h | 38 ++-------------------------\n" + " arch/mips/include/asm/futex.h | 25 ++----------------\n" + " arch/parisc/include/asm/futex.h | 25 ++----------------\n" + " arch/powerpc/include/asm/futex.h | 26 +++---------------\n" + " arch/s390/include/asm/futex.h | 23 +++-------------\n" + " arch/sh/include/asm/futex.h | 26 ++----------------\n" + " arch/sparc/include/asm/futex_64.h | 26 +++---------------\n" + " arch/tile/include/asm/futex.h | 40 +++-------------------------\n" + " arch/x86/include/asm/futex.h | 40 +++-------------------------\n" + " arch/xtensa/include/asm/futex.h | 27 +++----------------\n" + " include/asm-generic/futex.h | 50 ++++++------------------------------\n" + " kernel/futex.c | 39 ++++++++++++++++++++++++++++\n" + " 20 files changed, 126 insertions(+), 470 deletions(-)\n" + "\n" + "--- a/arch/alpha/include/asm/futex.h\n" + "+++ b/arch/alpha/include/asm/futex.h\n" + "@@ -29,18 +29,10 @@\n" + " \t:\t\"r\" (uaddr), \"r\"(oparg)\t\t\t\t\\\n" + " \t:\t\"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arc/include/asm/futex.h\n" + "+++ b/arch/arc/include/asm/futex.h\n" + "@@ -73,20 +73,11 @@\n" + " \n" + " #endif\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " #ifndef CONFIG_ARC_HAS_LLSC\n" + " \tpreempt_disable();\t/* to guarantee atomic r-m-w of futex op */\n" + " #endif\n" + "@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser\n" + " \tpreempt_enable();\n" + " #endif\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arm/include/asm/futex.h\n" + "+++ b/arch/arm/include/asm/futex.h\n" + "@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,\n" + " #endif /* !SMP */\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " #ifndef CONFIG_SMP\n" + " \tpreempt_disable();\n" + " #endif\n" + "@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \tpreempt_enable();\n" + " #endif\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/arm64/include/asm/futex.h\n" + "+++ b/arch/arm64/include/asm/futex.h\n" + "@@ -53,20 +53,10 @@\n" + " \t: \"memory\")\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (int)(encoded_op << 8) >> 20;\n" + "-\tint cmparg = (int)(encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1U << (oparg & 0x1f);\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/frv/include/asm/futex.h\n" + "+++ b/arch/frv/include/asm/futex.h\n" + "@@ -7,7 +7,8 @@\n" + " #include <asm/errno.h>\n" + " #include <asm/uaccess.h>\n" + " \n" + "-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);\n" + "+extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr);\n" + " \n" + " static inline int\n" + " futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,\n" + "--- a/arch/frv/kernel/futex.c\n" + "+++ b/arch/frv/kernel/futex.c\n" + "@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x\n" + " /*\n" + " * do the futex operations\n" + " */\n" + "-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS; break;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + " \treturn ret;\n" + " \n" + "-} /* end futex_atomic_op_inuser() */\n" + "+} /* end arch_futex_atomic_op_inuser() */\n" + "--- a/arch/hexagon/include/asm/futex.h\n" + "+++ b/arch/hexagon/include/asm/futex.h\n" + "@@ -31,18 +31,9 @@\n" + " \n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/ia64/include/asm/futex.h\n" + "+++ b/arch/ia64/include/asm/futex.h\n" + "@@ -45,18 +45,9 @@ do {\t\t\t\t\t\t\t\t\t\\\n" + " } while (0)\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/microblaze/include/asm/futex.h\n" + "+++ b/arch/microblaze/include/asm/futex.h\n" + "@@ -29,18 +29,9 @@\n" + " })\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/mips/include/asm/futex.h\n" + "+++ b/arch/mips/include/asm/futex.h\n" + "@@ -83,18 +83,9 @@\n" + " }\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/parisc/include/asm/futex.h\n" + "+++ b/arch/parisc/include/asm/futex.h\n" + "@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user\n" + " }\n" + " \n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + " \tunsigned long int flags;\n" + " \tu32 val;\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/powerpc/include/asm/futex.h\n" + "+++ b/arch/powerpc/include/asm/futex.h\n" + "@@ -31,18 +31,10 @@\n" + " \t: \"b\" (uaddr), \"i\" (-EFAULT), \"r\" (oparg) \\\n" + " \t: \"cr0\", \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/s390/include/asm/futex.h\n" + "+++ b/arch/s390/include/asm/futex.h\n" + "@@ -21,17 +21,12 @@\n" + " \t\t: \"0\" (-EFAULT), \"d\" (oparg), \"a\" (uaddr),\t\t\\\n" + " \t\t \"m\" (*uaddr) : \"cc\");\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, newval, ret;\n" + " \n" + " \tload_kernel_asce();\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + " \n" + " \tpagefault_disable();\n" + " \tswitch (op) {\n" + "@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser\n" + " \t}\n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/sh/include/asm/futex.h\n" + "+++ b/arch/sh/include/asm/futex.h\n" + "@@ -10,20 +10,11 @@\n" + " /* XXX: UP variants, fix for SH-4A and SMP.. */\n" + " #include <asm/futex-irq.h>\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + " \treturn ret;\n" + " }\n" + "--- a/arch/sparc/include/asm/futex_64.h\n" + "+++ b/arch/sparc/include/asm/futex_64.h\n" + "@@ -29,22 +29,14 @@\n" + " \t: \"r\" (uaddr), \"r\" (oparg), \"i\" (-EFAULT)\t\\\n" + " \t: \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tem;\n" + " \n" + "-\tif (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))\n" + "-\t\treturn -EFAULT;\n" + " \tif (unlikely((((unsigned long) uaddr) & 0x3UL)))\n" + " \t\treturn -EINVAL;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/tile/include/asm/futex.h\n" + "+++ b/arch/tile/include/asm/futex.h\n" + "@@ -106,12 +106,9 @@\n" + " \tlock = __atomic_hashed_lock((int __force *)uaddr)\n" + " #endif\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint uninitialized_var(val), ret;\n" + " \n" + " \t__futex_prolog();\n" + "@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser\n" + " \t/* The 32-bit futex code makes this assumption, so validate it here. */\n" + " \tBUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \tswitch (op) {\n" + " \tcase FUTEX_OP_SET:\n" + "@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser\n" + " \t}\n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (val == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (val != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (val < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (val >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (val <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (val > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = val;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/x86/include/asm/futex.h\n" + "+++ b/arch/x86/include/asm/futex.h\n" + "@@ -41,20 +41,11 @@\n" + " \t\t \"+m\" (*uaddr), \"=&r\" (tem)\t\t\\\n" + " \t\t : \"r\" (oparg), \"i\" (-EFAULT), \"1\" (0))\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret, tem;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + "-\n" + " \tpagefault_disable();\n" + " \n" + " \tswitch (op) {\n" + "@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ:\n" + "-\t\t\tret = (oldval == cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_NE:\n" + "-\t\t\tret = (oldval != cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LT:\n" + "-\t\t\tret = (oldval < cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GE:\n" + "-\t\t\tret = (oldval >= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_LE:\n" + "-\t\t\tret = (oldval <= cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tcase FUTEX_OP_CMP_GT:\n" + "-\t\t\tret = (oldval > cmparg);\n" + "-\t\t\tbreak;\n" + "-\t\tdefault:\n" + "-\t\t\tret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/arch/xtensa/include/asm/futex.h\n" + "+++ b/arch/xtensa/include/asm/futex.h\n" + "@@ -44,18 +44,10 @@\n" + " \t: \"r\" (uaddr), \"I\" (-EFAULT), \"r\" (oparg)\t\\\n" + " \t: \"memory\")\n" + " \n" + "-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,\n" + "+\t\tu32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " #if !XCHAL_HAVE_S32C1I\n" + " \treturn -ENOSYS;\n" + "@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (ret)\n" + "-\t\treturn ret;\n" + "-\n" + "-\tswitch (cmp) {\n" + "-\tcase FUTEX_OP_CMP_EQ: return (oldval == cmparg);\n" + "-\tcase FUTEX_OP_CMP_NE: return (oldval != cmparg);\n" + "-\tcase FUTEX_OP_CMP_LT: return (oldval < cmparg);\n" + "-\tcase FUTEX_OP_CMP_GE: return (oldval >= cmparg);\n" + "-\tcase FUTEX_OP_CMP_LE: return (oldval <= cmparg);\n" + "-\tcase FUTEX_OP_CMP_GT: return (oldval > cmparg);\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + " \n" + "-\treturn -ENOSYS;\n" + "+\treturn ret;\n" + " }\n" + " \n" + " static inline int\n" + "--- a/include/asm-generic/futex.h\n" + "+++ b/include/asm-generic/futex.h\n" + "@@ -13,7 +13,7 @@\n" + " */\n" + " \n" + " /**\n" + "- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n" + "+ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant\n" + " *\t\t\t argument and comparison of the previous\n" + " *\t\t\t futex value with another constant.\n" + " *\n" + "@@ -25,18 +25,11 @@\n" + " * <0 - On error\n" + " */\n" + " static inline int\n" + "-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval, ret;\n" + " \tu32 tmp;\n" + " \n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + " \tpreempt_disable();\n" + " \tpagefault_disable();\n" + " \n" + "@@ -74,17 +67,9 @@ out_pagefault_enable:\n" + " \tpagefault_enable();\n" + " \tpreempt_enable();\n" + " \n" + "-\tif (ret == 0) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (ret == 0)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,\n" + " \n" + " #else\n" + " static inline int\n" + "-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)\n" + "+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)\n" + " {\n" + "-\tint op = (encoded_op >> 28) & 7;\n" + "-\tint cmp = (encoded_op >> 24) & 15;\n" + "-\tint oparg = (encoded_op << 8) >> 20;\n" + "-\tint cmparg = (encoded_op << 20) >> 20;\n" + " \tint oldval = 0, ret;\n" + "-\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))\n" + "-\t\toparg = 1 << oparg;\n" + "-\n" + "-\tif (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "-\t\treturn -EFAULT;\n" + " \n" + " \tpagefault_disable();\n" + " \n" + "@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op,\n" + " \n" + " \tpagefault_enable();\n" + " \n" + "-\tif (!ret) {\n" + "-\t\tswitch (cmp) {\n" + "-\t\tcase FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;\n" + "-\t\tcase FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;\n" + "-\t\tdefault: ret = -ENOSYS;\n" + "-\t\t}\n" + "-\t}\n" + "+\tif (!ret)\n" + "+\t\t*oval = oldval;\n" + "+\n" + " \treturn ret;\n" + " }\n" + " \n" + "--- a/kernel/futex.c\n" + "+++ b/kernel/futex.c\n" + "@@ -1453,6 +1453,45 @@ out:\n" + " \treturn ret;\n" + " }\n" + " \n" + "+static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)\n" + "+{\n" + "+\tunsigned int op =\t (encoded_op & 0x70000000) >> 28;\n" + "+\tunsigned int cmp =\t (encoded_op & 0x0f000000) >> 24;\n" + "+\tint oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);\n" + "+\tint cmparg = sign_extend32(encoded_op & 0x00000fff, 12);\n" + "+\tint oldval, ret;\n" + "+\n" + "+\tif (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {\n" + "+\t\tif (oparg < 0 || oparg > 31)\n" + "+\t\t\treturn -EINVAL;\n" + "+\t\toparg = 1 << oparg;\n" + "+\t}\n" + "+\n" + "+\tif (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))\n" + "+\t\treturn -EFAULT;\n" + "+\n" + "+\tret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);\n" + "+\tif (ret)\n" + "+\t\treturn ret;\n" + "+\n" + "+\tswitch (cmp) {\n" + "+\tcase FUTEX_OP_CMP_EQ:\n" + "+\t\treturn oldval == cmparg;\n" + "+\tcase FUTEX_OP_CMP_NE:\n" + "+\t\treturn oldval != cmparg;\n" + "+\tcase FUTEX_OP_CMP_LT:\n" + "+\t\treturn oldval < cmparg;\n" + "+\tcase FUTEX_OP_CMP_GE:\n" + "+\t\treturn oldval >= cmparg;\n" + "+\tcase FUTEX_OP_CMP_LE:\n" + "+\t\treturn oldval <= cmparg;\n" + "+\tcase FUTEX_OP_CMP_GT:\n" + "+\t\treturn oldval > cmparg;\n" + "+\tdefault:\n" + "+\t\treturn -ENOSYS;\n" + "+\t}\n" + "+}\n" + "+\n" + " /*\n" + " * Wake up all waiters hashed on the physical page that is mapped\n" + " * to this virtual address:\n" + "\n" + "\n" + "Patches currently in stable-queue which might be from jslaby at suse.cz are\n" + "\n" + queue-4.4/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch -f87e12fcc4b63fa4f725f8fcbd2ab6c4f98754ab10827b6719644b9c25712681 +b69d697ae12e9c26411191bd51343be7639c38d73568195e53cf63ded892a738
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.