1#ifndef __i386_UACCESS_H
2#define __i386_UACCESS_H
3
4
5
6
7#include <linux/config.h>
8#include <linux/errno.h>
9#include <linux/thread_info.h>
10#include <linux/prefetch.h>
11#include <linux/string.h>
12#include <asm/page.h>
13
14#define VERIFY_READ 0
15#define VERIFY_WRITE 1
16
17
18
19
20
21
22
23
24
25#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
26
27
28#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL)
29#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
30
31#define get_ds() (KERNEL_DS)
32#define get_fs() (current_thread_info()->addr_limit)
33#define set_fs(x) (current_thread_info()->addr_limit = (x))
34
35#define segment_eq(a,b) ((a).seg == (b).seg)
36
37
38
39
40#ifdef CONFIG_X86_INTEL_USERCOPY
41extern struct movsl_mask {
42 int mask;
43} ____cacheline_aligned_in_smp movsl_mask;
44#endif
45
46#define __addr_ok(addr) ((unsigned long __force)(addr) < (current_thread_info()->addr_limit.seg))
47
48
49
50
51
52
53
54
55
56
57#define __range_ok(addr,size) ({ \
58 unsigned long flag,sum; \
59 __chk_user_ptr(addr); \
60 asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
61 :"=&r" (flag), "=r" (sum) \
62 :"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \
63 flag; })
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103static inline int verify_area(int type, const void __user * addr, unsigned long size)
104{
105 return access_ok(type,addr,size) ? 0 : -EFAULT;
106}
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122struct exception_table_entry
123{
124 unsigned long insn, fixup;
125};
126
127extern int fixup_exception(struct pt_regs *regs);
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144extern void __get_user_1(void);
145extern void __get_user_2(void);
146extern void __get_user_4(void);
147
148#define __get_user_x(size,ret,x,ptr) \
149 __asm__ __volatile__("call __get_user_" #size \
150 :"=a" (ret),"=d" (x) \
151 :"0" (ptr))
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172#define get_user(x,ptr) \
173({ int __ret_gu,__val_gu; \
174 __chk_user_ptr(ptr); \
175 switch(sizeof (*(ptr))) { \
176 case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
177 case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
178 case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break; \
179 default: __get_user_x(X,__ret_gu,__val_gu,ptr); break; \
180 } \
181 (x) = (__typeof__(*(ptr)))__val_gu; \
182 __ret_gu; \
183})
184
185extern void __put_user_bad(void);
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203#define put_user(x,ptr) \
204 __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227#define __get_user(x,ptr) \
228 __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250#define __put_user(x,ptr) \
251 __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
252
253#define __put_user_nocheck(x,ptr,size) \
254({ \
255 long __pu_err; \
256 __put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \
257 __pu_err; \
258})
259
260
261#define __put_user_check(x,ptr,size) \
262({ \
263 long __pu_err = -EFAULT; \
264 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
265 might_sleep(); \
266 if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
267 __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \
268 __pu_err; \
269})
270
271#define __put_user_u64(x, addr, err) \
272 __asm__ __volatile__( \
273 "1: movl %%eax,0(%2)\n" \
274 "2: movl %%edx,4(%2)\n" \
275 "3:\n" \
276 ".section .fixup,\"ax\"\n" \
277 "4: movl %3,%0\n" \
278 " jmp 3b\n" \
279 ".previous\n" \
280 ".section __ex_table,\"a\"\n" \
281 " .align 4\n" \
282 " .long 1b,4b\n" \
283 " .long 2b,4b\n" \
284 ".previous" \
285 : "=r"(err) \
286 : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
287
288#ifdef CONFIG_X86_WP_WORKS_OK
289
290#define __put_user_size(x,ptr,size,retval,errret) \
291do { \
292 retval = 0; \
293 __chk_user_ptr(ptr); \
294 switch (size) { \
295 case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break; \
296 case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \
297 case 4: __put_user_asm(x,ptr,retval,"l","","ir",errret); break; \
298 case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
299 default: __put_user_bad(); \
300 } \
301} while (0)
302
303#else
304
305#define __put_user_size(x,ptr,size,retval,errret) \
306do { \
307 __typeof__(*(ptr)) __pus_tmp = x; \
308 retval = 0; \
309 \
310 if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0)) \
311 retval = errret; \
312} while (0)
313
314#endif
315struct __large_struct { unsigned long buf[100]; };
316#define __m(x) (*(struct __large_struct *)(x))
317
318
319
320
321
322
323#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
324 __asm__ __volatile__( \
325 "1: mov"itype" %"rtype"1,%2\n" \
326 "2:\n" \
327 ".section .fixup,\"ax\"\n" \
328 "3: movl %3,%0\n" \
329 " jmp 2b\n" \
330 ".previous\n" \
331 ".section __ex_table,\"a\"\n" \
332 " .align 4\n" \
333 " .long 1b,3b\n" \
334 ".previous" \
335 : "=r"(err) \
336 : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
337
338
339#define __get_user_nocheck(x,ptr,size) \
340({ \
341 long __gu_err, __gu_val; \
342 __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\
343 (x) = (__typeof__(*(ptr)))__gu_val; \
344 __gu_err; \
345})
346
347extern long __get_user_bad(void);
348
349#define __get_user_size(x,ptr,size,retval,errret) \
350do { \
351 retval = 0; \
352 __chk_user_ptr(ptr); \
353 switch (size) { \
354 case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break; \
355 case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break; \
356 case 4: __get_user_asm(x,ptr,retval,"l","","=r",errret);break; \
357 default: (x) = __get_user_bad(); \
358 } \
359} while (0)
360
361#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
362 __asm__ __volatile__( \
363 "1: mov"itype" %2,%"rtype"1\n" \
364 "2:\n" \
365 ".section .fixup,\"ax\"\n" \
366 "3: movl %3,%0\n" \
367 " xor"itype" %"rtype"1,%"rtype"1\n" \
368 " jmp 2b\n" \
369 ".previous\n" \
370 ".section __ex_table,\"a\"\n" \
371 " .align 4\n" \
372 " .long 1b,3b\n" \
373 ".previous" \
374 : "=r"(err), ltype (x) \
375 : "m"(__m(addr)), "i"(errret), "0"(err))
376
377
378unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n);
379unsigned long __copy_from_user_ll(void *to, const void __user *from, unsigned long n);
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402static inline unsigned long
403__copy_to_user(void __user *to, const void *from, unsigned long n)
404{
405 if (__builtin_constant_p(n)) {
406 unsigned long ret;
407
408 switch (n) {
409 case 1:
410 __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1);
411 return ret;
412 case 2:
413 __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2);
414 return ret;
415 case 4:
416 __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4);
417 return ret;
418 }
419 }
420 return __copy_to_user_ll(to, from, n);
421}
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440static inline unsigned long
441__copy_from_user(void *to, const void __user *from, unsigned long n)
442{
443 if (__builtin_constant_p(n)) {
444 unsigned long ret;
445
446 switch (n) {
447 case 1:
448 __get_user_size(*(u8 *)to, from, 1, ret, 1);
449 return ret;
450 case 2:
451 __get_user_size(*(u16 *)to, from, 2, ret, 2);
452 return ret;
453 case 4:
454 __get_user_size(*(u32 *)to, from, 4, ret, 4);
455 return ret;
456 }
457 }
458 return __copy_from_user_ll(to, from, n);
459}
460
461unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);
462unsigned long copy_from_user(void *to,
463 const void __user *from, unsigned long n);
464long strncpy_from_user(char *dst, const char __user *src, long count);
465long __strncpy_from_user(char *dst, const char __user *src, long count);
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
482
483long strnlen_user(const char __user *str, long n);
484unsigned long clear_user(void __user *mem, unsigned long len);
485unsigned long __clear_user(void __user *mem, unsigned long len);
486
487#endif
488