aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-19 19:24:27 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-19 19:24:27 -1000
commita2f239f9efcee1ccd9a427b5835e24dc5779fab4 (patch)
tree649448c8caf20e3dba779bc86f598a1a24ecabe3
parentdc92e8485b615460a47dab04e784e077b6b6216a (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.h60
-rw-r--r--arch/x86/lib/getuser.S56
-rw-r--r--arch/x86/lib/putuser.S60
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