diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2012-09-07 14:23:27 +0100 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2012-09-07 15:54:38 +0100 |
commit | 373a6e24c6152096be1d540469be3aa19bb521c8 (patch) | |
tree | 8379481c894faae487d96f699532b261f3084f4a | |
parent | 632cb4ad190de8ede04fe1530b3561726d9c55fa (diff) | |
download | linux-aarch64-373a6e24c6152096be1d540469be3aa19bb521c8.tar.gz |
arm64: Ensure correct casting for get_user/put_user arguments
There may be cases where sizeof(x) != sizeof(*ptr) and this confuses the
compiler. This patch makes the conversion to/from "unsigned long" for
get_user as that's what the inline asm expects. For put_user, it makes
the conversion to __typeof__(*ptr). Most of the times, the compiler will
just ignore these and not generate additional code.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r-- | arch/arm64/include/asm/uaccess.h | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index cdc1666e47f..008f8481da6 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -128,23 +128,25 @@ static inline void set_fs(mm_segment_t fs) #define __get_user_err(x, ptr, err) \ do { \ + unsigned long __gu_val; \ __chk_user_ptr(ptr); \ switch (sizeof(*(ptr))) { \ case 1: \ - __get_user_asm("ldrb", "%w", (x), (ptr), (err)); \ + __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err)); \ break; \ case 2: \ - __get_user_asm("ldrh", "%w", (x), (ptr), (err)); \ + __get_user_asm("ldrh", "%w", __gu_val, (ptr), (err)); \ break; \ case 4: \ - __get_user_asm("ldr", "%w", (x), (ptr), (err)); \ + __get_user_asm("ldr", "%w", __gu_val, (ptr), (err)); \ break; \ case 8: \ - __get_user_asm("ldr", "%", (x), (ptr), (err)); \ + __get_user_asm("ldr", "%", __gu_val, (ptr), (err)); \ break; \ default: \ BUILD_BUG(); \ } \ + (x) = (__typeof__(*(ptr)))__gu_val; \ } while (0) #define __get_user(x, ptr) \ @@ -188,19 +190,20 @@ do { \ #define __put_user_err(x, ptr, err) \ do { \ + __typeof__(*(ptr)) __pu_val = (x); \ __chk_user_ptr(ptr); \ switch (sizeof(*(ptr))) { \ case 1: \ - __put_user_asm("strb", "%w", (x), (ptr), (err)); \ + __put_user_asm("strb", "%w", __pu_val, (ptr), (err)); \ break; \ case 2: \ - __put_user_asm("strh", "%w", (x), (ptr), (err)); \ + __put_user_asm("strh", "%w", __pu_val, (ptr), (err)); \ break; \ case 4: \ - __put_user_asm("str", "%w", (x), (ptr), (err)); \ + __put_user_asm("str", "%w", __pu_val, (ptr), (err)); \ break; \ case 8: \ - __put_user_asm("str", "%", (x), (ptr), (err)); \ + __put_user_asm("str", "%", __pu_val, (ptr), (err)); \ break; \ default: \ BUILD_BUG(); \ |