lkml.org 
[lkml]   [2019]   [Nov]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 29/75] ARM: uaccess: remove put_user() code duplication
    Date
    From: Russell King <rmk+kernel@arm.linux.org.uk>

    Commit 9f73bd8bb445e0cbe4bcef6d4cfc788f1e184007 upstream.

    Remove the code duplication between put_user() and __put_user(). The
    code which selected the implementation based upon the pointer size, and
    declared the local variable to hold the value to be put are common to
    both implementations.

    Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
    Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/arm/include/asm/uaccess.h | 106 ++++++++++++++++++-----------------------
    1 file changed, 49 insertions(+), 57 deletions(-)

    --- a/arch/arm/include/asm/uaccess.h
    +++ b/arch/arm/include/asm/uaccess.h
    @@ -238,49 +238,23 @@ extern int __put_user_2(void *, unsigned
    extern int __put_user_4(void *, unsigned int);
    extern int __put_user_8(void *, unsigned long long);

    -#define __put_user_x(__r2, __p, __e, __l, __s) \
    - __asm__ __volatile__ ( \
    - __asmeq("%0", "r0") __asmeq("%2", "r2") \
    - __asmeq("%3", "r1") \
    - "bl __put_user_" #__s \
    - : "=&r" (__e) \
    - : "0" (__p), "r" (__r2), "r" (__l) \
    - : "ip", "lr", "cc")
    -
    -#define __put_user_check(x, p) \
    +#define __put_user_check(__pu_val, __ptr, __err, __s) \
    ({ \
    unsigned long __limit = current_thread_info()->addr_limit - 1; \
    - const typeof(*(p)) __user *__tmp_p = (p); \
    - register const typeof(*(p)) __r2 asm("r2") = (x); \
    - register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
    + register typeof(__pu_val) __r2 asm("r2") = __pu_val; \
    + register const void __user *__p asm("r0") = __ptr; \
    register unsigned long __l asm("r1") = __limit; \
    register int __e asm("r0"); \
    - unsigned int __ua_flags = uaccess_save_and_enable(); \
    - switch (sizeof(*(__p))) { \
    - case 1: \
    - __put_user_x(__r2, __p, __e, __l, 1); \
    - break; \
    - case 2: \
    - __put_user_x(__r2, __p, __e, __l, 2); \
    - break; \
    - case 4: \
    - __put_user_x(__r2, __p, __e, __l, 4); \
    - break; \
    - case 8: \
    - __put_user_x(__r2, __p, __e, __l, 8); \
    - break; \
    - default: __e = __put_user_bad(); break; \
    - } \
    - uaccess_restore(__ua_flags); \
    - __e; \
    + __asm__ __volatile__ ( \
    + __asmeq("%0", "r0") __asmeq("%2", "r2") \
    + __asmeq("%3", "r1") \
    + "bl __put_user_" #__s \
    + : "=&r" (__e) \
    + : "0" (__p), "r" (__r2), "r" (__l) \
    + : "ip", "lr", "cc"); \
    + __err = __e; \
    })

    -#define put_user(x, p) \
    - ({ \
    - might_fault(); \
    - __put_user_check(x, p); \
    - })
    -
    #else /* CONFIG_MMU */

    /*
    @@ -298,7 +272,7 @@ static inline void set_fs(mm_segment_t f
    }

    #define get_user(x, p) __get_user(x, p)
    -#define put_user(x, p) __put_user(x, p)
    +#define __put_user_check __put_user_nocheck

    #endif /* CONFIG_MMU */

    @@ -389,36 +363,54 @@ do { \
    #define __get_user_asm_word(x, addr, err) \
    __get_user_asm(x, addr, err, ldr)

    +
    +#define __put_user_switch(x, ptr, __err, __fn) \
    + do { \
    + const __typeof__(*(ptr)) __user *__pu_ptr = (ptr); \
    + __typeof__(*(ptr)) __pu_val = (x); \
    + unsigned int __ua_flags; \
    + might_fault(); \
    + __ua_flags = uaccess_save_and_enable(); \
    + switch (sizeof(*(ptr))) { \
    + case 1: __fn(__pu_val, __pu_ptr, __err, 1); break; \
    + case 2: __fn(__pu_val, __pu_ptr, __err, 2); break; \
    + case 4: __fn(__pu_val, __pu_ptr, __err, 4); break; \
    + case 8: __fn(__pu_val, __pu_ptr, __err, 8); break; \
    + default: __err = __put_user_bad(); break; \
    + } \
    + uaccess_restore(__ua_flags); \
    + } while (0)
    +
    +#define put_user(x, ptr) \
    +({ \
    + int __pu_err = 0; \
    + __put_user_switch((x), (ptr), __pu_err, __put_user_check); \
    + __pu_err; \
    +})
    +
    #define __put_user(x, ptr) \
    ({ \
    long __pu_err = 0; \
    - __put_user_err((x), (ptr), __pu_err); \
    + __put_user_switch((x), (ptr), __pu_err, __put_user_nocheck); \
    __pu_err; \
    })

    #define __put_user_error(x, ptr, err) \
    ({ \
    - __put_user_err((x), (ptr), err); \
    + __put_user_switch((x), (ptr), (err), __put_user_nocheck); \
    (void) 0; \
    })

    -#define __put_user_err(x, ptr, err) \
    -do { \
    - unsigned long __pu_addr = (unsigned long)(ptr); \
    - unsigned int __ua_flags; \
    - __typeof__(*(ptr)) __pu_val = (x); \
    - __chk_user_ptr(ptr); \
    - might_fault(); \
    - __ua_flags = uaccess_save_and_enable(); \
    - switch (sizeof(*(ptr))) { \
    - case 1: __put_user_asm_byte(__pu_val, __pu_addr, err); break; \
    - case 2: __put_user_asm_half(__pu_val, __pu_addr, err); break; \
    - case 4: __put_user_asm_word(__pu_val, __pu_addr, err); break; \
    - case 8: __put_user_asm_dword(__pu_val, __pu_addr, err); break; \
    - default: __put_user_bad(); \
    - } \
    - uaccess_restore(__ua_flags); \
    -} while (0)
    +#define __put_user_nocheck(x, __pu_ptr, __err, __size) \
    + do { \
    + unsigned long __pu_addr = (unsigned long)__pu_ptr; \
    + __put_user_nocheck_##__size(x, __pu_addr, __err); \
    + } while (0)
    +
    +#define __put_user_nocheck_1 __put_user_asm_byte
    +#define __put_user_nocheck_2 __put_user_asm_half
    +#define __put_user_nocheck_4 __put_user_asm_word
    +#define __put_user_nocheck_8 __put_user_asm_dword

    #define __put_user_asm(x, __pu_addr, err, instr) \
    __asm__ __volatile__( \

    \
     
     \ /
      Last update: 2019-11-08 19:54    [W:5.302 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site