Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * __put_user functions.
4 *
5 * (C) Copyright 2005 Linus Torvalds
6 * (C) Copyright 2005 Andi Kleen
7 * (C) Copyright 2008 Glauber Costa
8 *
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 */
14#include <linux/linkage.h>
15#include <asm/thread_info.h>
16#include <asm/errno.h>
17#include <asm/asm.h>
18#include <asm/smap.h>
19#include <asm/export.h>
20
21
22/*
23 * __put_user_X
24 *
25 * Inputs: %eax[:%edx] contains the data
26 * %ecx contains the address
27 *
28 * Outputs: %ecx is error code (0 or -EFAULT)
29 *
30 * Clobbers: %ebx needed for task pointer
31 *
32 * These functions should not modify any other registers,
33 * as they get called from within inline assembly.
34 */
35
36.macro check_range size:req
37.if IS_ENABLED(CONFIG_X86_64)
38 mov %rcx, %rbx
39 sar $63, %rbx
40 or %rbx, %rcx
41.else
42 cmp $TASK_SIZE_MAX-\size+1, %ecx
43 jae .Lbad_put_user
44.endif
45.endm
46
47.text
48SYM_FUNC_START(__put_user_1)
49 check_range size=1
50 ASM_STAC
511: movb %al,(%_ASM_CX)
52 xor %ecx,%ecx
53 ASM_CLAC
54 RET
55SYM_FUNC_END(__put_user_1)
56EXPORT_SYMBOL(__put_user_1)
57
58SYM_FUNC_START(__put_user_nocheck_1)
59 ASM_STAC
602: movb %al,(%_ASM_CX)
61 xor %ecx,%ecx
62 ASM_CLAC
63 RET
64SYM_FUNC_END(__put_user_nocheck_1)
65EXPORT_SYMBOL(__put_user_nocheck_1)
66
67SYM_FUNC_START(__put_user_2)
68 check_range size=2
69 ASM_STAC
703: movw %ax,(%_ASM_CX)
71 xor %ecx,%ecx
72 ASM_CLAC
73 RET
74SYM_FUNC_END(__put_user_2)
75EXPORT_SYMBOL(__put_user_2)
76
77SYM_FUNC_START(__put_user_nocheck_2)
78 ASM_STAC
794: movw %ax,(%_ASM_CX)
80 xor %ecx,%ecx
81 ASM_CLAC
82 RET
83SYM_FUNC_END(__put_user_nocheck_2)
84EXPORT_SYMBOL(__put_user_nocheck_2)
85
86SYM_FUNC_START(__put_user_4)
87 check_range size=4
88 ASM_STAC
895: movl %eax,(%_ASM_CX)
90 xor %ecx,%ecx
91 ASM_CLAC
92 RET
93SYM_FUNC_END(__put_user_4)
94EXPORT_SYMBOL(__put_user_4)
95
96SYM_FUNC_START(__put_user_nocheck_4)
97 ASM_STAC
986: movl %eax,(%_ASM_CX)
99 xor %ecx,%ecx
100 ASM_CLAC
101 RET
102SYM_FUNC_END(__put_user_nocheck_4)
103EXPORT_SYMBOL(__put_user_nocheck_4)
104
105SYM_FUNC_START(__put_user_8)
106 check_range size=8
107 ASM_STAC
1087: mov %_ASM_AX,(%_ASM_CX)
109#ifdef CONFIG_X86_32
1108: movl %edx,4(%_ASM_CX)
111#endif
112 xor %ecx,%ecx
113 ASM_CLAC
114 RET
115SYM_FUNC_END(__put_user_8)
116EXPORT_SYMBOL(__put_user_8)
117
118SYM_FUNC_START(__put_user_nocheck_8)
119 ASM_STAC
1209: mov %_ASM_AX,(%_ASM_CX)
121#ifdef CONFIG_X86_32
12210: movl %edx,4(%_ASM_CX)
123#endif
124 xor %ecx,%ecx
125 ASM_CLAC
126 RET
127SYM_FUNC_END(__put_user_nocheck_8)
128EXPORT_SYMBOL(__put_user_nocheck_8)
129
130SYM_CODE_START_LOCAL(__put_user_handle_exception)
131 ASM_CLAC
132.Lbad_put_user:
133 movl $-EFAULT,%ecx
134 RET
135SYM_CODE_END(__put_user_handle_exception)
136
137 _ASM_EXTABLE(1b, __put_user_handle_exception)
138 _ASM_EXTABLE(2b, __put_user_handle_exception)
139 _ASM_EXTABLE(3b, __put_user_handle_exception)
140 _ASM_EXTABLE(4b, __put_user_handle_exception)
141 _ASM_EXTABLE(5b, __put_user_handle_exception)
142 _ASM_EXTABLE(6b, __put_user_handle_exception)
143 _ASM_EXTABLE(7b, __put_user_handle_exception)
144 _ASM_EXTABLE(9b, __put_user_handle_exception)
145#ifdef CONFIG_X86_32
146 _ASM_EXTABLE(8b, __put_user_handle_exception)
147 _ASM_EXTABLE(10b, __put_user_handle_exception)
148#endif