This source file includes following definitions.
- probe_read_common
- probe_write_common
- __probe_kernel_read
- __probe_user_read
- __probe_kernel_write
- __probe_user_write
- strncpy_from_unsafe
- strncpy_from_unsafe_user
- strnlen_unsafe_user
1
2
3
4
5 #include <linux/export.h>
6 #include <linux/mm.h>
7 #include <linux/uaccess.h>
8
9 static __always_inline long
10 probe_read_common(void *dst, const void __user *src, size_t size)
11 {
12 long ret;
13
14 pagefault_disable();
15 ret = __copy_from_user_inatomic(dst, src, size);
16 pagefault_enable();
17
18 return ret ? -EFAULT : 0;
19 }
20
21 static __always_inline long
22 probe_write_common(void __user *dst, const void *src, size_t size)
23 {
24 long ret;
25
26 pagefault_disable();
27 ret = __copy_to_user_inatomic(dst, src, size);
28 pagefault_enable();
29
30 return ret ? -EFAULT : 0;
31 }
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 long __weak probe_kernel_read(void *dst, const void *src, size_t size)
49 __attribute__((alias("__probe_kernel_read")));
50
51 long __probe_kernel_read(void *dst, const void *src, size_t size)
52 {
53 long ret;
54 mm_segment_t old_fs = get_fs();
55
56 set_fs(KERNEL_DS);
57 ret = probe_read_common(dst, (__force const void __user *)src, size);
58 set_fs(old_fs);
59
60 return ret;
61 }
62 EXPORT_SYMBOL_GPL(probe_kernel_read);
63
64
65
66
67
68
69
70
71
72
73
74 long __weak probe_user_read(void *dst, const void __user *src, size_t size)
75 __attribute__((alias("__probe_user_read")));
76
77 long __probe_user_read(void *dst, const void __user *src, size_t size)
78 {
79 long ret = -EFAULT;
80 mm_segment_t old_fs = get_fs();
81
82 set_fs(USER_DS);
83 if (access_ok(src, size))
84 ret = probe_read_common(dst, src, size);
85 set_fs(old_fs);
86
87 return ret;
88 }
89 EXPORT_SYMBOL_GPL(probe_user_read);
90
91
92
93
94
95
96
97
98
99
100
101 long __weak probe_kernel_write(void *dst, const void *src, size_t size)
102 __attribute__((alias("__probe_kernel_write")));
103
104 long __probe_kernel_write(void *dst, const void *src, size_t size)
105 {
106 long ret;
107 mm_segment_t old_fs = get_fs();
108
109 set_fs(KERNEL_DS);
110 ret = probe_write_common((__force void __user *)dst, src, size);
111 set_fs(old_fs);
112
113 return ret;
114 }
115 EXPORT_SYMBOL_GPL(probe_kernel_write);
116
117
118
119
120
121
122
123
124
125
126
127 long __weak probe_user_write(void __user *dst, const void *src, size_t size)
128 __attribute__((alias("__probe_user_write")));
129
130 long __probe_user_write(void __user *dst, const void *src, size_t size)
131 {
132 long ret = -EFAULT;
133 mm_segment_t old_fs = get_fs();
134
135 set_fs(USER_DS);
136 if (access_ok(dst, size))
137 ret = probe_write_common(dst, src, size);
138 set_fs(old_fs);
139
140 return ret;
141 }
142 EXPORT_SYMBOL_GPL(probe_user_write);
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count)
162 {
163 mm_segment_t old_fs = get_fs();
164 const void *src = unsafe_addr;
165 long ret;
166
167 if (unlikely(count <= 0))
168 return 0;
169
170 set_fs(KERNEL_DS);
171 pagefault_disable();
172
173 do {
174 ret = __get_user(*dst++, (const char __user __force *)src++);
175 } while (dst[-1] && ret == 0 && src - unsafe_addr < count);
176
177 dst[-1] = '\0';
178 pagefault_enable();
179 set_fs(old_fs);
180
181 return ret ? -EFAULT : src - unsafe_addr;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 long strncpy_from_unsafe_user(char *dst, const void __user *unsafe_addr,
203 long count)
204 {
205 mm_segment_t old_fs = get_fs();
206 long ret;
207
208 if (unlikely(count <= 0))
209 return 0;
210
211 set_fs(USER_DS);
212 pagefault_disable();
213 ret = strncpy_from_user(dst, unsafe_addr, count);
214 pagefault_enable();
215 set_fs(old_fs);
216
217 if (ret >= count) {
218 ret = count;
219 dst[ret - 1] = '\0';
220 } else if (ret > 0) {
221 ret++;
222 }
223
224 return ret;
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 long strnlen_unsafe_user(const void __user *unsafe_addr, long count)
244 {
245 mm_segment_t old_fs = get_fs();
246 int ret;
247
248 set_fs(USER_DS);
249 pagefault_disable();
250 ret = strnlen_user(unsafe_addr, count);
251 pagefault_enable();
252 set_fs(old_fs);
253
254 return ret;
255 }