Skip to content

Commit 44c5b67

Browse files
KAGA-KOKOPeter Zijlstra
authored andcommitted
ARM: uaccess: Implement missing __get_user_asm_dword()
When CONFIG_CPU_SPECTRE=n then get_user() is missing the 8 byte ASM variant for no real good reason. This prevents using get_user(u64) in generic code. Implement it as a sequence of two 4-byte reads with LE/BE awareness and make the unsigned long (or long long) type for the intermediate variable to read into dependend on the the target type. The __long_type() macro and idea was lifted from PowerPC. Thanks to Christophe for pointing it out. Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Closes: https://lore.kernel.org/oe-kbuild-all/202509120155.pFgwfeUD-lkp@intel.com/ Link: https://patch.msgid.link/20251027083745.168468637@linutronix.de
1 parent 6146a0f commit 44c5b67

1 file changed

Lines changed: 25 additions & 1 deletion

File tree

arch/arm/include/asm/uaccess.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,17 @@ extern int __put_user_8(void *, unsigned long long);
283283
__gu_err; \
284284
})
285285

286+
/*
287+
* This is a type: either unsigned long, if the argument fits into
288+
* that type, or otherwise unsigned long long.
289+
*/
290+
#define __long_type(x) \
291+
__typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
292+
286293
#define __get_user_err(x, ptr, err, __t) \
287294
do { \
288295
unsigned long __gu_addr = (unsigned long)(ptr); \
289-
unsigned long __gu_val; \
296+
__long_type(x) __gu_val; \
290297
unsigned int __ua_flags; \
291298
__chk_user_ptr(ptr); \
292299
might_fault(); \
@@ -295,6 +302,7 @@ do { \
295302
case 1: __get_user_asm_byte(__gu_val, __gu_addr, err, __t); break; \
296303
case 2: __get_user_asm_half(__gu_val, __gu_addr, err, __t); break; \
297304
case 4: __get_user_asm_word(__gu_val, __gu_addr, err, __t); break; \
305+
case 8: __get_user_asm_dword(__gu_val, __gu_addr, err, __t); break; \
298306
default: (__gu_val) = __get_user_bad(); \
299307
} \
300308
uaccess_restore(__ua_flags); \
@@ -353,6 +361,22 @@ do { \
353361
#define __get_user_asm_word(x, addr, err, __t) \
354362
__get_user_asm(x, addr, err, "ldr" __t)
355363

364+
#ifdef __ARMEB__
365+
#define __WORD0_OFFS 4
366+
#define __WORD1_OFFS 0
367+
#else
368+
#define __WORD0_OFFS 0
369+
#define __WORD1_OFFS 4
370+
#endif
371+
372+
#define __get_user_asm_dword(x, addr, err, __t) \
373+
({ \
374+
unsigned long __w0, __w1; \
375+
__get_user_asm(__w0, addr + __WORD0_OFFS, err, "ldr" __t); \
376+
__get_user_asm(__w1, addr + __WORD1_OFFS, err, "ldr" __t); \
377+
(x) = ((u64)__w1 << 32) | (u64) __w0; \
378+
})
379+
356380
#define __put_user_switch(x, ptr, __err, __fn) \
357381
do { \
358382
const __typeof__(*(ptr)) __user *__pu_ptr = (ptr); \

0 commit comments

Comments
 (0)