diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2015-12-21 09:36:21 +0100 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-12-21 09:36:21 +0100 |
commit | 0529357f102b96f68bc199f858d1c3b07f4b674c (patch) | |
tree | eaa047952a768099e00a5245afa0d84799df6990 /arch/arm/lib/uaccess_with_memcpy.c | |
parent | a9f1a3e4c1c7dc82711bc22dc52c7b0d6912ed56 (diff) | |
parent | 4ef7675344d687a0ef5b0d7c0cee12da005870c0 (diff) | |
download | op-kernel-dev-0529357f102b96f68bc199f858d1c3b07f4b674c.zip op-kernel-dev-0529357f102b96f68bc199f858d1c3b07f4b674c.tar.gz |
Merge tag 'v4.4-rc6' into devel
Linux 4.4-rc6
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 d72b909..588bbc2 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 |