[3/3] MIPS: uaccess: Take EVA into account in [__]clear_user
diff mbox

Message ID -
State Accepted
Delegated to: Ralf Baechle
Headers show

Commit Message

James Hogan Aug. 5, 2015, 3:41 p.m. UTC
__clear_user() (and clear_user() which uses it), always access the user
mode address space, which results in EVA store instructions when EVA is
enabled even if the current user address limit is KERNEL_DS.

Fix this by adding a new symbol __bzero_kernel for the normal kernel
address space bzero in EVA mode, and call that from __clear_user() if
eva_kernel_access().

Signed-off-by: James Hogan <>
Cc: Ralf Baechle <>
Cc: Markos Chandras <>
Cc: Paul Burton <>
Cc: Leonid Yegoshin <>
Cc: 
---
I've not Cc'd stable on this patch as eva_kernel_access() was only added
in 4.2. I'll submit a backport once it is merged.
---
 arch/mips/include/asm/uaccess.h | 32 ++++++++++++++++++++++----------
 arch/mips/kernel/mips_ksyms.c   |  2 ++
 arch/mips/lib/memset.S          |  2 ++
 3 files changed, 26 insertions(+), 10 deletions(-)

Comments

James Hogan Jan. 4, 2016, 6:13 p.m. UTC | #1
Hi stable folk,

On Wed, Aug 05, 2015 at 04:41:39PM +0100, James Hogan wrote:
> __clear_user() (and clear_user() which uses it), always access the user
> mode address space, which results in EVA store instructions when EVA is
> enabled even if the current user address limit is KERNEL_DS.
> 
> Fix this by adding a new symbol __bzero_kernel for the normal kernel
> address space bzero in EVA mode, and call that from __clear_user() if
> eva_kernel_access().
> 
> Signed-off-by: James Hogan <>
> Cc: Ralf Baechle <>
> Cc: Markos Chandras <>
> Cc: Paul Burton <>
> Cc: Leonid Yegoshin <>
> Cc: 
> ---
> I've not Cc'd stable on this patch as eva_kernel_access() was only added
> in 4.2. I'll submit a backport once it is merged.

This is now merged, but a little later than anticipated. Please can
patch 2 & 3 be applied to stable >= v4.2.

The upstream commits are:

6f06a2c45d8d714ea3b11a360b4a7191e52acaa4
("MIPS: uaccess: Take EVA into account in __copy_from_user()")

d6a428fb583738ad685c91a684748cdee7b2a05f
("MIPS: uaccess: Take EVA into account in [__]clear_user")

As stated above, I'll provide backports for v3.15 <= version < v4.2.

Thanks
James

> ---
>  arch/mips/include/asm/uaccess.h | 32 ++++++++++++++++++++++----------
>  arch/mips/kernel/mips_ksyms.c   |  2 ++
>  arch/mips/lib/memset.S          |  2 ++
>  3 files changed, 26 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
> index 5014e187df23..2e3b3991cf0b 100644
> --- a/arch/mips/include/asm/uaccess.h
> +++ b/arch/mips/include/asm/uaccess.h
> @@ -1235,16 +1235,28 @@ __clear_user(void __user *addr, __kernel_size_t size)
>  {
>  	__kernel_size_t res;
>  
> -	might_fault();
> -	__asm__ __volatile__(
> -		"move\t$4, %1\n\t"
> -		"move\t$5, $0\n\t"
> -		"move\t$6, %2\n\t"
> -		__MODULE_JAL(__bzero)
> -		"move\t%0, $6"
> -		: "=r" (res)
> -		: "r" (addr), "r" (size)
> -		: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
> +	if (eva_kernel_access()) {
> +		__asm__ __volatile__(
> +			"move\t$4, %1\n\t"
> +			"move\t$5, $0\n\t"
> +			"move\t$6, %2\n\t"
> +			__MODULE_JAL(__bzero_kernel)
> +			"move\t%0, $6"
> +			: "=r" (res)
> +			: "r" (addr), "r" (size)
> +			: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
> +	} else {
> +		might_fault();
> +		__asm__ __volatile__(
> +			"move\t$4, %1\n\t"
> +			"move\t$5, $0\n\t"
> +			"move\t$6, %2\n\t"
> +			__MODULE_JAL(__bzero)
> +			"move\t%0, $6"
> +			: "=r" (res)
> +			: "r" (addr), "r" (size)
> +			: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
> +	}
>  
>  	return res;
>  }
> diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
> index 291af0b5c482..e2b6ab74643d 100644
> --- a/arch/mips/kernel/mips_ksyms.c
> +++ b/arch/mips/kernel/mips_ksyms.c
> @@ -17,6 +17,7 @@
>  #include <asm/fpu.h>
>  #include <asm/msa.h>
>  
> +extern void *__bzero_kernel(void *__s, size_t __count);
>  extern void *__bzero(void *__s, size_t __count);
>  extern long __strncpy_from_kernel_nocheck_asm(char *__to,
>  					      const char *__from, long __len);
> @@ -64,6 +65,7 @@ EXPORT_SYMBOL(__copy_from_user_eva);
>  EXPORT_SYMBOL(__copy_in_user_eva);
>  EXPORT_SYMBOL(__copy_to_user_eva);
>  EXPORT_SYMBOL(__copy_user_inatomic_eva);
> +EXPORT_SYMBOL(__bzero_kernel);
>  #endif
>  EXPORT_SYMBOL(__bzero);
>  EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm);
> diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
> index b8e63fd00375..8f0019a2e5c8 100644
> --- a/arch/mips/lib/memset.S
> +++ b/arch/mips/lib/memset.S
> @@ -283,6 +283,8 @@ LEAF(memset)
>  1:
>  #ifndef CONFIG_EVA
>  FEXPORT(__bzero)
> +#else
> +FEXPORT(__bzero_kernel)
>  #endif
>  	__BUILD_BZERO LEGACY_MODE
>  
> -- 
> 2.3.6
>

Patch
diff mbox

diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index 5014e187df23..2e3b3991cf0b 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -1235,16 +1235,28 @@  __clear_user(void __user *addr, __kernel_size_t size)
 {
 	__kernel_size_t res;
 
-	might_fault();
-	__asm__ __volatile__(
-		"move\t$4, %1\n\t"
-		"move\t$5, $0\n\t"
-		"move\t$6, %2\n\t"
-		__MODULE_JAL(__bzero)
-		"move\t%0, $6"
-		: "=r" (res)
-		: "r" (addr), "r" (size)
-		: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+	if (eva_kernel_access()) {
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, $0\n\t"
+			"move\t$6, %2\n\t"
+			__MODULE_JAL(__bzero_kernel)
+			"move\t%0, $6"
+			: "=r" (res)
+			: "r" (addr), "r" (size)
+			: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+	} else {
+		might_fault();
+		__asm__ __volatile__(
+			"move\t$4, %1\n\t"
+			"move\t$5, $0\n\t"
+			"move\t$6, %2\n\t"
+			__MODULE_JAL(__bzero)
+			"move\t%0, $6"
+			: "=r" (res)
+			: "r" (addr), "r" (size)
+			: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+	}
 
 	return res;
 }
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 291af0b5c482..e2b6ab74643d 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -17,6 +17,7 @@ 
 #include <asm/fpu.h>
 #include <asm/msa.h>
 
+extern void *__bzero_kernel(void *__s, size_t __count);
 extern void *__bzero(void *__s, size_t __count);
 extern long __strncpy_from_kernel_nocheck_asm(char *__to,
 					      const char *__from, long __len);
@@ -64,6 +65,7 @@  EXPORT_SYMBOL(__copy_from_user_eva);
 EXPORT_SYMBOL(__copy_in_user_eva);
 EXPORT_SYMBOL(__copy_to_user_eva);
 EXPORT_SYMBOL(__copy_user_inatomic_eva);
+EXPORT_SYMBOL(__bzero_kernel);
 #endif
 EXPORT_SYMBOL(__bzero);
 EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm);
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index b8e63fd00375..8f0019a2e5c8 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -283,6 +283,8 @@  LEAF(memset)
 1:
 #ifndef CONFIG_EVA
 FEXPORT(__bzero)
+#else
+FEXPORT(__bzero_kernel)
 #endif
 	__BUILD_BZERO LEGACY_MODE