diff options
Diffstat (limited to 'arch/arm/lib/uaccess_with_memcpy.c')
| -rw-r--r-- | arch/arm/lib/uaccess_with_memcpy.c | 29 | 
1 files changed, 23 insertions, 6 deletions
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index d72b90905132..588bbc288396 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c @@ -88,6 +88,7 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)  static unsigned long noinline  __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)  { +	unsigned long ua_flags;  	int atomic;  	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { @@ -118,7 +119,9 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)  		if (tocopy > n)  			tocopy = n; +		ua_flags = uaccess_save_and_enable();  		memcpy((void *)to, from, tocopy); +		uaccess_restore(ua_flags);  		to += tocopy;  		from += tocopy;  		n -= tocopy; @@ -145,14 +148,21 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n)  	 * With frame pointer disabled, tail call optimization kicks in  	 * as well making this test almost invisible.  	 */ -	if (n < 64) -		return __copy_to_user_std(to, from, n); -	return __copy_to_user_memcpy(to, from, n); +	if (n < 64) { +		unsigned long ua_flags = uaccess_save_and_enable(); +		n = __copy_to_user_std(to, from, n); +		uaccess_restore(ua_flags); +	} else { +		n = __copy_to_user_memcpy(to, from, n); +	} +	return n;  }  static unsigned long noinline  __clear_user_memset(void __user *addr, unsigned long n)  { +	unsigned long ua_flags; +  	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {  		memset((void *)addr, 0, n);  		return 0; @@ -175,7 +185,9 @@ __clear_user_memset(void __user *addr, unsigned long n)  		if (tocopy > n)  			tocopy = n; +		ua_flags = uaccess_save_and_enable();  		memset((void *)addr, 0, tocopy); +		uaccess_restore(ua_flags);  		addr += tocopy;  		n -= tocopy; @@ -193,9 +205,14 @@ out:  unsigned long arm_clear_user(void __user *addr, unsigned long n)  {  	/* See rational for this in __copy_to_user() above. */ -	if (n < 64) -		return __clear_user_std(addr, n); -	return __clear_user_memset(addr, n); +	if (n < 64) { +		unsigned long ua_flags = uaccess_save_and_enable(); +		n = __clear_user_std(addr, n); +		uaccess_restore(ua_flags); +	} else { +		n = __clear_user_memset(addr, n); +	} +	return n;  }  #if 0  | 
