blob: 975c9c18263d2afd926c12a8bfffe0c2d72d43cd [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * __put_user functions.
4 *
5 * (C) Copyright 2005 Linus Torvalds
Glauber Costa5cbbc3b2008-06-24 17:40:14 -03006 * (C) Copyright 2005 Andi Kleen
7 * (C) Copyright 2008 Glauber Costa
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * These functions have a non-standard call interface
10 * to make them more efficient, especially as they
11 * return an error value in addition to the "real"
12 * return value.
13 */
Masahiro Yamada94ea9c02023-08-06 23:59:56 +090014#include <linux/export.h>
Jan Beulich00e065e2007-05-02 19:27:05 +020015#include <linux/linkage.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <asm/thread_info.h>
Glauber Costa5cbbc3b2008-06-24 17:40:14 -030017#include <asm/errno.h>
Glauber Costa2528de42008-06-24 17:36:31 -030018#include <asm/asm.h>
H. Peter Anvin63bcff22012-09-21 12:43:12 -070019#include <asm/smap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
21/*
22 * __put_user_X
23 *
24 * Inputs: %eax[:%edx] contains the data
25 * %ecx contains the address
26 *
Linus Torvaldsd55564c2020-04-08 13:36:49 -070027 * Outputs: %ecx is error code (0 or -EFAULT)
28 *
29 * Clobbers: %ebx needed for task pointer
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 *
31 * These functions should not modify any other registers,
32 * as they get called from within inline assembly.
33 */
34
Kirill A. Shutemovb19b74b2023-03-12 14:25:56 +030035.macro check_range size:req
36.if IS_ENABLED(CONFIG_X86_64)
37 mov %rcx, %rbx
38 sar $63, %rbx
39 or %rbx, %rcx
40.else
41 cmp $TASK_SIZE_MAX-\size+1, %ecx
42 jae .Lbad_put_user
43.endif
44.endm
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46.text
Jiri Slaby6dcc5622019-10-11 13:51:04 +020047SYM_FUNC_START(__put_user_1)
Kirill A. Shutemovb19b74b2023-03-12 14:25:56 +030048 check_range size=1
H. Peter Anvin63bcff22012-09-21 12:43:12 -070049 ASM_STAC
Glauber Costa2528de42008-06-24 17:36:31 -0300501: movb %al,(%_ASM_CX)
Linus Torvaldsd55564c2020-04-08 13:36:49 -070051 xor %ecx,%ecx
Josh Poimboeuf82e844a2019-07-17 20:36:44 -050052 ASM_CLAC
Peter Zijlstraf94909c2021-12-04 14:43:40 +010053 RET
Jiri Slaby6dcc5622019-10-11 13:51:04 +020054SYM_FUNC_END(__put_user_1)
Al Viro784d5692016-01-11 11:04:34 -050055EXPORT_SYMBOL(__put_user_1)
Thomas Gleixnercb855972022-09-15 13:11:16 +020056
57SYM_FUNC_START(__put_user_nocheck_1)
Thomas Gleixnercb855972022-09-15 13:11:16 +020058 ASM_STAC
592: movb %al,(%_ASM_CX)
60 xor %ecx,%ecx
61 ASM_CLAC
62 RET
63SYM_FUNC_END(__put_user_nocheck_1)
Linus Torvaldsd55564c2020-04-08 13:36:49 -070064EXPORT_SYMBOL(__put_user_nocheck_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
Jiri Slaby6dcc5622019-10-11 13:51:04 +020066SYM_FUNC_START(__put_user_2)
Kirill A. Shutemovb19b74b2023-03-12 14:25:56 +030067 check_range size=2
H. Peter Anvin63bcff22012-09-21 12:43:12 -070068 ASM_STAC
Thomas Gleixnercb855972022-09-15 13:11:16 +0200693: movw %ax,(%_ASM_CX)
Linus Torvaldsd55564c2020-04-08 13:36:49 -070070 xor %ecx,%ecx
Josh Poimboeuf82e844a2019-07-17 20:36:44 -050071 ASM_CLAC
Peter Zijlstraf94909c2021-12-04 14:43:40 +010072 RET
Jiri Slaby6dcc5622019-10-11 13:51:04 +020073SYM_FUNC_END(__put_user_2)
Al Viro784d5692016-01-11 11:04:34 -050074EXPORT_SYMBOL(__put_user_2)
Thomas Gleixnercb855972022-09-15 13:11:16 +020075
76SYM_FUNC_START(__put_user_nocheck_2)
Thomas Gleixnercb855972022-09-15 13:11:16 +020077 ASM_STAC
784: movw %ax,(%_ASM_CX)
79 xor %ecx,%ecx
80 ASM_CLAC
81 RET
82SYM_FUNC_END(__put_user_nocheck_2)
Linus Torvaldsd55564c2020-04-08 13:36:49 -070083EXPORT_SYMBOL(__put_user_nocheck_2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
Jiri Slaby6dcc5622019-10-11 13:51:04 +020085SYM_FUNC_START(__put_user_4)
Kirill A. Shutemovb19b74b2023-03-12 14:25:56 +030086 check_range size=4
H. Peter Anvin63bcff22012-09-21 12:43:12 -070087 ASM_STAC
Thomas Gleixnercb855972022-09-15 13:11:16 +0200885: movl %eax,(%_ASM_CX)
Linus Torvaldsd55564c2020-04-08 13:36:49 -070089 xor %ecx,%ecx
Josh Poimboeuf82e844a2019-07-17 20:36:44 -050090 ASM_CLAC
Peter Zijlstraf94909c2021-12-04 14:43:40 +010091 RET
Jiri Slaby6dcc5622019-10-11 13:51:04 +020092SYM_FUNC_END(__put_user_4)
Al Viro784d5692016-01-11 11:04:34 -050093EXPORT_SYMBOL(__put_user_4)
Thomas Gleixnercb855972022-09-15 13:11:16 +020094
95SYM_FUNC_START(__put_user_nocheck_4)
Thomas Gleixnercb855972022-09-15 13:11:16 +020096 ASM_STAC
976: movl %eax,(%_ASM_CX)
98 xor %ecx,%ecx
99 ASM_CLAC
100 RET
101SYM_FUNC_END(__put_user_nocheck_4)
Linus Torvaldsd55564c2020-04-08 13:36:49 -0700102EXPORT_SYMBOL(__put_user_nocheck_4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Jiri Slaby6dcc5622019-10-11 13:51:04 +0200104SYM_FUNC_START(__put_user_8)
Kirill A. Shutemovb19b74b2023-03-12 14:25:56 +0300105 check_range size=8
H. Peter Anvin63bcff22012-09-21 12:43:12 -0700106 ASM_STAC
Thomas Gleixnercb855972022-09-15 13:11:16 +02001077: mov %_ASM_AX,(%_ASM_CX)
Glauber Costa5cbbc3b2008-06-24 17:40:14 -0300108#ifdef CONFIG_X86_32
Thomas Gleixnercb855972022-09-15 13:11:16 +02001098: movl %edx,4(%_ASM_CX)
Glauber Costa5cbbc3b2008-06-24 17:40:14 -0300110#endif
Linus Torvaldsd55564c2020-04-08 13:36:49 -0700111 xor %ecx,%ecx
Josh Poimboeuf82e844a2019-07-17 20:36:44 -0500112 ASM_CLAC
113 RET
Jiri Slaby6dcc5622019-10-11 13:51:04 +0200114SYM_FUNC_END(__put_user_8)
Al Viro784d5692016-01-11 11:04:34 -0500115EXPORT_SYMBOL(__put_user_8)
Thomas Gleixnercb855972022-09-15 13:11:16 +0200116
117SYM_FUNC_START(__put_user_nocheck_8)
Thomas Gleixnercb855972022-09-15 13:11:16 +0200118 ASM_STAC
1199: mov %_ASM_AX,(%_ASM_CX)
120#ifdef CONFIG_X86_32
12110: movl %edx,4(%_ASM_CX)
122#endif
123 xor %ecx,%ecx
124 ASM_CLAC
125 RET
126SYM_FUNC_END(__put_user_nocheck_8)
Linus Torvaldsd55564c2020-04-08 13:36:49 -0700127EXPORT_SYMBOL(__put_user_nocheck_8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Nadav Amit5516c892023-05-25 11:42:44 -0700129SYM_CODE_START_LOCAL(__put_user_handle_exception)
Josh Poimboeuf82e844a2019-07-17 20:36:44 -0500130 ASM_CLAC
Jiri Slaby98ededb2019-09-06 09:55:50 +0200131.Lbad_put_user:
Linus Torvaldsd55564c2020-04-08 13:36:49 -0700132 movl $-EFAULT,%ecx
Josh Poimboeuf82e844a2019-07-17 20:36:44 -0500133 RET
Nadav Amit5516c892023-05-25 11:42:44 -0700134SYM_CODE_END(__put_user_handle_exception)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
Qiuxu Zhuo8eed4e02024-01-29 14:38:42 +0800136 _ASM_EXTABLE_UA(1b, __put_user_handle_exception)
137 _ASM_EXTABLE_UA(2b, __put_user_handle_exception)
138 _ASM_EXTABLE_UA(3b, __put_user_handle_exception)
139 _ASM_EXTABLE_UA(4b, __put_user_handle_exception)
140 _ASM_EXTABLE_UA(5b, __put_user_handle_exception)
141 _ASM_EXTABLE_UA(6b, __put_user_handle_exception)
142 _ASM_EXTABLE_UA(7b, __put_user_handle_exception)
143 _ASM_EXTABLE_UA(9b, __put_user_handle_exception)
Thomas Gleixnercb855972022-09-15 13:11:16 +0200144#ifdef CONFIG_X86_32
Qiuxu Zhuo8eed4e02024-01-29 14:38:42 +0800145 _ASM_EXTABLE_UA(8b, __put_user_handle_exception)
146 _ASM_EXTABLE_UA(10b, __put_user_handle_exception)
Glauber Costa5cbbc3b2008-06-24 17:40:14 -0300147#endif