diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-19 19:24:27 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-19 19:24:27 -1000 |
| commit | a2f239f9efcee1ccd9a427b5835e24dc5779fab4 (patch) | |
| tree | 649448c8caf20e3dba779bc86f598a1a24ecabe3 | |
| parent | dc92e8485b615460a47dab04e784e077b6b6216a (diff) | |
x86/uaccess: Remove __get_user() and __put_user()uaccess-cleanups
Nothing that builds on x86 uses __get_user() or __put_user() any more.
They were the "unchecked" user accessors: no range check, on the
assumption that the caller had already done an access_ok(). That
stopped buying anything once every user access had to be enabled and
disabled on its own, and on x86 __get_user() had become slower than
get_user(), since it does an lfence where get_user() checks the address
with a couple of plain instructions. Several of the last users were
also relying on them for things they were never meant to do: accessing
kernel addresses, or staying quiet in atomic context.
Remove the macros and the out-of-line __{get,put}_user_nocheck_N helpers
behind them, so that new users cannot appear.
Other architectures still provide their own versions. UML gets its
accessors from asm-generic and is not affected. arm64's __get_user()
and __put_user() have always been the same as get_user() and put_user(),
so there is no hurry there.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | arch/x86/include/asm/uaccess.h | 60 | ||||
| -rw-r--r-- | arch/x86/lib/getuser.S | 56 | ||||
| -rw-r--r-- | arch/x86/lib/putuser.S | 60 |
3 files changed, 10 insertions, 166 deletions
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 3a0dd3c2b233..f4700ad6b5ec 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -28,10 +28,6 @@ extern int __get_user_1(void); extern int __get_user_2(void); extern int __get_user_4(void); extern int __get_user_8(void); -extern int __get_user_nocheck_1(void); -extern int __get_user_nocheck_2(void); -extern int __get_user_nocheck_4(void); -extern int __get_user_nocheck_8(void); extern int __get_user_bad(void); #define __uaccess_begin() stac() @@ -56,10 +52,9 @@ extern int __get_user_bad(void); __builtin_choose_expr(sizeof(x)<=sizeof(type),(unsigned type)0,not) /* - * This is used for both get_user() and __get_user() to expand to - * the proper special function call that has odd calling conventions - * due to returning both a value and an error, and that depends on - * the size of the pointer passed in. + * This is used by get_user() to expand to the proper special function + * call that has odd calling conventions due to returning both a value + * and an error, and that depends on the size of the pointer passed in. * * Careful: we have to cast the result to the type of the pointer * for sign reasons. @@ -107,29 +102,6 @@ extern int __get_user_bad(void); */ #define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); }) -/** - * __get_user - Get a simple variable from user space, with less checking. - * @x: Variable to store result. - * @ptr: Source address, in user space. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * This macro copies a single simple variable from user space to kernel - * space. It supports simple types like char and int, but not larger - * data types like structures or arrays. - * - * @ptr must have pointer-to-simple-variable type, and the result of - * dereferencing @ptr must be assignable to @x without a cast. - * - * Caller must check the pointer with access_ok() before calling this - * function. - * - * Return: zero on success, or -EFAULT on error. - * On error, the variable @x is set to zero. - */ -#define __get_user(x,ptr) do_get_user_call(get_user_nocheck,x,ptr) - #ifdef CONFIG_X86_32 #define __put_user_goto_u64(x, addr, label) \ @@ -156,10 +128,6 @@ extern void __put_user_1(void); extern void __put_user_2(void); extern void __put_user_4(void); extern void __put_user_8(void); -extern void __put_user_nocheck_1(void); -extern void __put_user_nocheck_2(void); -extern void __put_user_nocheck_4(void); -extern void __put_user_nocheck_8(void); /* * ptr must be evaluated and assigned to the temporary __ptr_pu before @@ -207,28 +175,6 @@ extern void __put_user_nocheck_8(void); */ #define put_user(x, ptr) ({ might_fault(); do_put_user_call(put_user,x,ptr); }) -/** - * __put_user - Write a simple value into user space, with less checking. - * @x: Value to copy to user space. - * @ptr: Destination address, in user space. - * - * Context: User context only. This function may sleep if pagefaults are - * enabled. - * - * This macro copies a single simple value from kernel space to user - * space. It supports simple types like char and int, but not larger - * data types like structures or arrays. - * - * @ptr must have pointer-to-simple-variable type, and @x must be assignable - * to the result of dereferencing @ptr. - * - * Caller must check the pointer with access_ok() before calling this - * function. - * - * Return: zero on success, or -EFAULT on error. - */ -#define __put_user(x, ptr) do_put_user_call(put_user_nocheck,x,ptr) - #define __put_user_size(x, ptr, size, label) \ do { \ __typeof__(*(ptr)) __x = (x); /* eval x once */ \ diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index 9d5654b8a72a..7c79eca08b0a 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * __get_user functions. + * The out-of-line helpers for get_user(). * * (C) Copyright 1998 Linus Torvalds * (C) Copyright 2005 Andi Kleen @@ -37,8 +37,6 @@ #include <asm/smap.h> #include <asm/runtime-const.h> -#define ASM_BARRIER_NOSPEC ALTERNATIVE "", "lfence", X86_FEATURE_LFENCE_RDTSC - .macro check_range size:req .if IS_ENABLED(CONFIG_X86_64) RUNTIME_CONST_PTR USER_PTR_MAX, rdx @@ -111,58 +109,6 @@ SYM_FUNC_START(__get_user_8) SYM_FUNC_END(__get_user_8) EXPORT_SYMBOL(__get_user_8) -/* .. and the same for __get_user, just without the range checks */ -SYM_FUNC_START(__get_user_nocheck_1) - ANNOTATE_NOENDBR - ASM_STAC - ASM_BARRIER_NOSPEC - UACCESS movzbl (%_ASM_AX),%edx - xor %eax,%eax - ASM_CLAC - RET -SYM_FUNC_END(__get_user_nocheck_1) -EXPORT_SYMBOL(__get_user_nocheck_1) - -SYM_FUNC_START(__get_user_nocheck_2) - ANNOTATE_NOENDBR - ASM_STAC - ASM_BARRIER_NOSPEC - UACCESS movzwl (%_ASM_AX),%edx - xor %eax,%eax - ASM_CLAC - RET -SYM_FUNC_END(__get_user_nocheck_2) -EXPORT_SYMBOL(__get_user_nocheck_2) - -SYM_FUNC_START(__get_user_nocheck_4) - ANNOTATE_NOENDBR - ASM_STAC - ASM_BARRIER_NOSPEC - UACCESS movl (%_ASM_AX),%edx - xor %eax,%eax - ASM_CLAC - RET -SYM_FUNC_END(__get_user_nocheck_4) -EXPORT_SYMBOL(__get_user_nocheck_4) - -SYM_FUNC_START(__get_user_nocheck_8) - ANNOTATE_NOENDBR - ASM_STAC - ASM_BARRIER_NOSPEC -#ifdef CONFIG_X86_64 - UACCESS movq (%_ASM_AX),%rdx -#else - xor %ecx,%ecx - UACCESS movl (%_ASM_AX),%edx - UACCESS movl 4(%_ASM_AX),%ecx -#endif - xor %eax,%eax - ASM_CLAC - RET -SYM_FUNC_END(__get_user_nocheck_8) -EXPORT_SYMBOL(__get_user_nocheck_8) - - SYM_CODE_START_LOCAL(__get_user_handle_exception) ASM_CLAC .Lbad_get_user: diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S index 46d9e9b98a61..9ad19f907485 100644 --- a/arch/x86/lib/putuser.S +++ b/arch/x86/lib/putuser.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * __put_user functions. + * The out-of-line helpers for put_user(). * * (C) Copyright 2005 Linus Torvalds * (C) Copyright 2005 Andi Kleen @@ -56,65 +56,35 @@ SYM_FUNC_START(__put_user_1) SYM_FUNC_END(__put_user_1) EXPORT_SYMBOL(__put_user_1) -SYM_FUNC_START(__put_user_nocheck_1) - ANNOTATE_NOENDBR - ASM_STAC -2: movb %al,(%_ASM_CX) - xor %ecx,%ecx - ASM_CLAC - RET -SYM_FUNC_END(__put_user_nocheck_1) -EXPORT_SYMBOL(__put_user_nocheck_1) - SYM_FUNC_START(__put_user_2) ANNOTATE_NOENDBR check_range size=2 ASM_STAC -3: movw %ax,(%_ASM_CX) +2: movw %ax,(%_ASM_CX) xor %ecx,%ecx ASM_CLAC RET SYM_FUNC_END(__put_user_2) EXPORT_SYMBOL(__put_user_2) -SYM_FUNC_START(__put_user_nocheck_2) - ANNOTATE_NOENDBR - ASM_STAC -4: movw %ax,(%_ASM_CX) - xor %ecx,%ecx - ASM_CLAC - RET -SYM_FUNC_END(__put_user_nocheck_2) -EXPORT_SYMBOL(__put_user_nocheck_2) - SYM_FUNC_START(__put_user_4) ANNOTATE_NOENDBR check_range size=4 ASM_STAC -5: movl %eax,(%_ASM_CX) +3: movl %eax,(%_ASM_CX) xor %ecx,%ecx ASM_CLAC RET SYM_FUNC_END(__put_user_4) EXPORT_SYMBOL(__put_user_4) -SYM_FUNC_START(__put_user_nocheck_4) - ANNOTATE_NOENDBR - ASM_STAC -6: movl %eax,(%_ASM_CX) - xor %ecx,%ecx - ASM_CLAC - RET -SYM_FUNC_END(__put_user_nocheck_4) -EXPORT_SYMBOL(__put_user_nocheck_4) - SYM_FUNC_START(__put_user_8) ANNOTATE_NOENDBR check_range size=8 ASM_STAC -7: mov %_ASM_AX,(%_ASM_CX) +4: mov %_ASM_AX,(%_ASM_CX) #ifdef CONFIG_X86_32 -8: movl %edx,4(%_ASM_CX) +5: movl %edx,4(%_ASM_CX) #endif xor %ecx,%ecx ASM_CLAC @@ -122,19 +92,6 @@ SYM_FUNC_START(__put_user_8) SYM_FUNC_END(__put_user_8) EXPORT_SYMBOL(__put_user_8) -SYM_FUNC_START(__put_user_nocheck_8) - ANNOTATE_NOENDBR - ASM_STAC -9: mov %_ASM_AX,(%_ASM_CX) -#ifdef CONFIG_X86_32 -10: movl %edx,4(%_ASM_CX) -#endif - xor %ecx,%ecx - ASM_CLAC - RET -SYM_FUNC_END(__put_user_nocheck_8) -EXPORT_SYMBOL(__put_user_nocheck_8) - SYM_CODE_START_LOCAL(__put_user_handle_exception) ASM_CLAC .Lbad_put_user: @@ -146,11 +103,6 @@ SYM_CODE_END(__put_user_handle_exception) _ASM_EXTABLE_UA(2b, __put_user_handle_exception) _ASM_EXTABLE_UA(3b, __put_user_handle_exception) _ASM_EXTABLE_UA(4b, __put_user_handle_exception) - _ASM_EXTABLE_UA(5b, __put_user_handle_exception) - _ASM_EXTABLE_UA(6b, __put_user_handle_exception) - _ASM_EXTABLE_UA(7b, __put_user_handle_exception) - _ASM_EXTABLE_UA(9b, __put_user_handle_exception) #ifdef CONFIG_X86_32 - _ASM_EXTABLE_UA(8b, __put_user_handle_exception) - _ASM_EXTABLE_UA(10b, __put_user_handle_exception) + _ASM_EXTABLE_UA(5b, __put_user_handle_exception) #endif |
