[PATCH 4.10 60/69] parisc: Fix get_user() for 64-bit value on 32-bit kernel

2017-04-19 Thread Greg Kroah-Hartman
4.10-stable review patch.  If anyone has any objections, please let me know.

--

From: Helge Deller 

commit 3f795cef0ecdf9bc980dd058d49bdab4b19af1d3 upstream.

This fixes a bug in which the upper 32-bits of a 64-bit value which is
read by get_user() was lost on a 32-bit kernel.
While touching this code, split out pre-loading of %sr2 space register
and clean up code indent.

Signed-off-by: Helge Deller 
Signed-off-by: Greg Kroah-Hartman 

---
 arch/parisc/include/asm/uaccess.h |   86 --
 1 file changed, 55 insertions(+), 31 deletions(-)

--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -42,10 +42,10 @@ static inline long access_ok(int type, c
 #define get_user __get_user
 
 #if !defined(CONFIG_64BIT)
-#define LDD_USER(ptr)  __get_user_asm64(ptr)
+#define LDD_USER(val, ptr) __get_user_asm64(val, ptr)
 #define STD_USER(x, ptr)   __put_user_asm64(x, ptr)
 #else
-#define LDD_USER(ptr)  __get_user_asm("ldd", ptr)
+#define LDD_USER(val, ptr) __get_user_asm(val, "ldd", ptr)
 #define STD_USER(x, ptr)   __put_user_asm("std", x, ptr)
 #endif
 
@@ -100,63 +100,87 @@ struct exception_data {
" mtsp %0,%%sr2\n\t"\
: : "r"(get_fs()) : )
 
-#define __get_user(x, ptr)   \
-({   \
-   register long __gu_err __asm__ ("r8") = 0;   \
-   register long __gu_val;  \
-\
-   load_sr2();  \
-   switch (sizeof(*(ptr))) {\
-   case 1: __get_user_asm("ldb", ptr); break;   \
-   case 2: __get_user_asm("ldh", ptr); break;   \
-   case 4: __get_user_asm("ldw", ptr); break;   \
-   case 8: LDD_USER(ptr);  break;   \
-   default: BUILD_BUG(); break; \
-   }\
-\
-   (x) = (__force __typeof__(*(ptr))) __gu_val; \
-   __gu_err;\
+#define __get_user_internal(val, ptr)  \
+({ \
+   register long __gu_err __asm__ ("r8") = 0;  \
+   \
+   switch (sizeof(*(ptr))) {   \
+   case 1: __get_user_asm(val, "ldb", ptr); break; \
+   case 2: __get_user_asm(val, "ldh", ptr); break; \
+   case 4: __get_user_asm(val, "ldw", ptr); break; \
+   case 8: LDD_USER(val, ptr); break;  \
+   default: BUILD_BUG();   \
+   }   \
+   \
+   __gu_err;   \
 })
 
-#define __get_user_asm(ldx, ptr)\
+#define __get_user(val, ptr)   \
+({ \
+   load_sr2(); \
+   __get_user_internal(val, ptr);  \
+})
+
+#define __get_user_asm(val, ldx, ptr)  \
+{  \
+   register long __gu_val; \
+   \
__asm__("1: " ldx " 0(%%sr2,%2),%0\n"   \
"9:\n"  \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
: "=r"(__gu_val), "=r"(__gu_err)\
-   : "r"(ptr), "1"(__gu_err));
+   : "r"(ptr), "1"(__gu_err)); \
+   \
+   (val) = (__force __typeof__(*(ptr))) __gu_val;  \
+}
 
 #if !defined(CONFIG_64BIT)
 
-#define __get_user_asm64(ptr)  \
+#define __get_user_asm64(val, ptr) \
+{  \
+   union { \
+   unsigned long long  l;  \
+   __typeof__(*(ptr))  t;  \
+   } __gu_tmp; \
+   \
__asm__("   copy %%r0,%R0\n"\
"1: ldw 0(%%sr2,%2),%0\n"   \
"2: ldw 4(%%sr2,%2),%R0\n"  \
"9:\n"  \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
-   : "=r"(__gu_val), "=r"(__gu_err)\
-   : "r"(ptr), "1"(__gu_err));
+ 

[PATCH 4.10 60/69] parisc: Fix get_user() for 64-bit value on 32-bit kernel

2017-04-19 Thread Greg Kroah-Hartman
4.10-stable review patch.  If anyone has any objections, please let me know.

--

From: Helge Deller 

commit 3f795cef0ecdf9bc980dd058d49bdab4b19af1d3 upstream.

This fixes a bug in which the upper 32-bits of a 64-bit value which is
read by get_user() was lost on a 32-bit kernel.
While touching this code, split out pre-loading of %sr2 space register
and clean up code indent.

Signed-off-by: Helge Deller 
Signed-off-by: Greg Kroah-Hartman 

---
 arch/parisc/include/asm/uaccess.h |   86 --
 1 file changed, 55 insertions(+), 31 deletions(-)

--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -42,10 +42,10 @@ static inline long access_ok(int type, c
 #define get_user __get_user
 
 #if !defined(CONFIG_64BIT)
-#define LDD_USER(ptr)  __get_user_asm64(ptr)
+#define LDD_USER(val, ptr) __get_user_asm64(val, ptr)
 #define STD_USER(x, ptr)   __put_user_asm64(x, ptr)
 #else
-#define LDD_USER(ptr)  __get_user_asm("ldd", ptr)
+#define LDD_USER(val, ptr) __get_user_asm(val, "ldd", ptr)
 #define STD_USER(x, ptr)   __put_user_asm("std", x, ptr)
 #endif
 
@@ -100,63 +100,87 @@ struct exception_data {
" mtsp %0,%%sr2\n\t"\
: : "r"(get_fs()) : )
 
-#define __get_user(x, ptr)   \
-({   \
-   register long __gu_err __asm__ ("r8") = 0;   \
-   register long __gu_val;  \
-\
-   load_sr2();  \
-   switch (sizeof(*(ptr))) {\
-   case 1: __get_user_asm("ldb", ptr); break;   \
-   case 2: __get_user_asm("ldh", ptr); break;   \
-   case 4: __get_user_asm("ldw", ptr); break;   \
-   case 8: LDD_USER(ptr);  break;   \
-   default: BUILD_BUG(); break; \
-   }\
-\
-   (x) = (__force __typeof__(*(ptr))) __gu_val; \
-   __gu_err;\
+#define __get_user_internal(val, ptr)  \
+({ \
+   register long __gu_err __asm__ ("r8") = 0;  \
+   \
+   switch (sizeof(*(ptr))) {   \
+   case 1: __get_user_asm(val, "ldb", ptr); break; \
+   case 2: __get_user_asm(val, "ldh", ptr); break; \
+   case 4: __get_user_asm(val, "ldw", ptr); break; \
+   case 8: LDD_USER(val, ptr); break;  \
+   default: BUILD_BUG();   \
+   }   \
+   \
+   __gu_err;   \
 })
 
-#define __get_user_asm(ldx, ptr)\
+#define __get_user(val, ptr)   \
+({ \
+   load_sr2(); \
+   __get_user_internal(val, ptr);  \
+})
+
+#define __get_user_asm(val, ldx, ptr)  \
+{  \
+   register long __gu_val; \
+   \
__asm__("1: " ldx " 0(%%sr2,%2),%0\n"   \
"9:\n"  \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
: "=r"(__gu_val), "=r"(__gu_err)\
-   : "r"(ptr), "1"(__gu_err));
+   : "r"(ptr), "1"(__gu_err)); \
+   \
+   (val) = (__force __typeof__(*(ptr))) __gu_val;  \
+}
 
 #if !defined(CONFIG_64BIT)
 
-#define __get_user_asm64(ptr)  \
+#define __get_user_asm64(val, ptr) \
+{  \
+   union { \
+   unsigned long long  l;  \
+   __typeof__(*(ptr))  t;  \
+   } __gu_tmp; \
+   \
__asm__("   copy %%r0,%R0\n"\
"1: ldw 0(%%sr2,%2),%0\n"   \
"2: ldw 4(%%sr2,%2),%R0\n"  \
"9:\n"  \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
-   : "=r"(__gu_val), "=r"(__gu_err)\
-   : "r"(ptr), "1"(__gu_err));
+   : "="(__gu_tmp.l), "=r"(__gu_err) \
+