1#ifndef __i386_UACCESS_H
2#define __i386_UACCESS_H
3
4
5
6
7#include <linux/config.h>
8#include <linux/sched.h>
9#include <linux/prefetch.h>
10#include <asm/page.h>
11
12#define VERIFY_READ 0
13#define VERIFY_WRITE 1
14
15
16
17
18
19
20
21
22
23#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
24
25
26#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
27#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
28
29#define get_ds() (KERNEL_DS)
30#define get_fs() (current->addr_limit)
31#define set_fs(x) (current->addr_limit = (x))
32
33#define segment_eq(a,b) ((a).seg == (b).seg)
34
35extern int __verify_write(const void *, unsigned long);
36
37#define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg))
38
39
40
41
42
43
44
45
46
47
48#define __range_ok(addr,size) ({ \
49 unsigned long flag,sum; \
50 asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
51 :"=&r" (flag), "=r" (sum) \
52 :"1" (addr),"g" ((int)(size)),"g" (current->addr_limit.seg)); \
53 flag; })
54
55#ifdef CONFIG_X86_WP_WORKS_OK
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
77
78#else
79
80#define access_ok(type,addr,size) ( (__range_ok(addr,size) == 0) && \
81 ((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || \
82 segment_eq(get_fs(),KERNEL_DS) || \
83 __verify_write((void *)(addr),(size))))
84
85#endif
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104static inline int verify_area(int type, const void * addr, unsigned long size)
105{
106 return access_ok(type,addr,size) ? 0 : -EFAULT;
107}
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123struct exception_table_entry
124{
125 unsigned long insn, fixup;
126};
127
128
129extern unsigned long search_exception_table(unsigned long);
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147extern void __get_user_1(void);
148extern void __get_user_2(void);
149extern void __get_user_4(void);
150
151#define __get_user_x(size,ret,x,ptr) \
152 __asm__ __volatile__("call __get_user_" #size \
153 :"=a" (ret),"=d" (x) \
154 :"0" (ptr))
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175#define get_user(x,ptr) \
176({ int __ret_gu,__val_gu; \
177 switch(sizeof (*(ptr))) { \
178 case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
179 case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
180 case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break; \
181 default: __get_user_x(X,__ret_gu,__val_gu,ptr); break; \
182 } \
183 (x) = (__typeof__(*(ptr)))__val_gu; \
184 __ret_gu; \
185})
186
187extern void __put_user_1(void);
188extern void __put_user_2(void);
189extern void __put_user_4(void);
190extern void __put_user_8(void);
191
192extern void __put_user_bad(void);
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211#define put_user(x,ptr) \
212 __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235#define __get_user(x,ptr) \
236 __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258#define __put_user(x,ptr) \
259 __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
260
261#define __put_user_nocheck(x,ptr,size) \
262({ \
263 long __pu_err; \
264 __put_user_size((x),(ptr),(size),__pu_err); \
265 __pu_err; \
266})
267
268
269#define __put_user_check(x,ptr,size) \
270({ \
271 long __pu_err = -EFAULT; \
272 __typeof__(*(ptr)) *__pu_addr = (ptr); \
273 if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
274 __put_user_size((x),__pu_addr,(size),__pu_err); \
275 __pu_err; \
276})
277
278#define __put_user_u64(x, addr, err) \
279 __asm__ __volatile__( \
280 "1: movl %%eax,0(%2)\n" \
281 "2: movl %%edx,4(%2)\n" \
282 "3:\n" \
283 ".section .fixup,\"ax\"\n" \
284 "4: movl %3,%0\n" \
285 " jmp 3b\n" \
286 ".previous\n" \
287 ".section __ex_table,\"a\"\n" \
288 " .align 4\n" \
289 " .long 1b,4b\n" \
290 " .long 2b,4b\n" \
291 ".previous" \
292 : "=r"(err) \
293 : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
294
295#define __put_user_size(x,ptr,size,retval) \
296do { \
297 retval = 0; \
298 switch (size) { \
299 case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break; \
300 case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break; \
301 case 4: __put_user_asm(x,ptr,retval,"l","","ir"); break; \
302 case 8: __put_user_u64(x,ptr,retval); break; \
303 default: __put_user_bad(); \
304 } \
305} while (0)
306
307struct __large_struct { unsigned long buf[100]; };
308#define __m(x) (*(struct __large_struct *)(x))
309
310
311
312
313
314
315#define __put_user_asm(x, addr, err, itype, rtype, ltype) \
316 __asm__ __volatile__( \
317 "1: mov"itype" %"rtype"1,%2\n" \
318 "2:\n" \
319 ".section .fixup,\"ax\"\n" \
320 "3: movl %3,%0\n" \
321 " jmp 2b\n" \
322 ".previous\n" \
323 ".section __ex_table,\"a\"\n" \
324 " .align 4\n" \
325 " .long 1b,3b\n" \
326 ".previous" \
327 : "=r"(err) \
328 : ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err))
329
330
331#define __get_user_nocheck(x,ptr,size) \
332({ \
333 long __gu_err, __gu_val; \
334 __get_user_size(__gu_val,(ptr),(size),__gu_err); \
335 (x) = (__typeof__(*(ptr)))__gu_val; \
336 __gu_err; \
337})
338
339extern long __get_user_bad(void);
340
341#define __get_user_size(x,ptr,size,retval) \
342do { \
343 retval = 0; \
344 switch (size) { \
345 case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break; \
346 case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break; \
347 case 4: __get_user_asm(x,ptr,retval,"l","","=r"); break; \
348 default: (x) = __get_user_bad(); \
349 } \
350} while (0)
351
352#define __get_user_asm(x, addr, err, itype, rtype, ltype) \
353 __asm__ __volatile__( \
354 "1: mov"itype" %2,%"rtype"1\n" \
355 "2:\n" \
356 ".section .fixup,\"ax\"\n" \
357 "3: movl %3,%0\n" \
358 " xor"itype" %"rtype"1,%"rtype"1\n" \
359 " jmp 2b\n" \
360 ".previous\n" \
361 ".section __ex_table,\"a\"\n" \
362 " .align 4\n" \
363 " .long 1b,3b\n" \
364 ".previous" \
365 : "=r"(err), ltype (x) \
366 : "m"(__m(addr)), "i"(-EFAULT), "0"(err))
367
368
369
370
371
372
373
374#define __copy_user(to,from,size) \
375do { \
376 int __d0, __d1; \
377 __asm__ __volatile__( \
378 "0: rep; movsl\n" \
379 " movl %3,%0\n" \
380 "1: rep; movsb\n" \
381 "2:\n" \
382 ".section .fixup,\"ax\"\n" \
383 "3: lea 0(%3,%0,4),%0\n" \
384 " jmp 2b\n" \
385 ".previous\n" \
386 ".section __ex_table,\"a\"\n" \
387 " .align 4\n" \
388 " .long 0b,3b\n" \
389 " .long 1b,2b\n" \
390 ".previous" \
391 : "=&c"(size), "=&D" (__d0), "=&S" (__d1) \
392 : "r"(size & 3), "0"(size / 4), "1"(to), "2"(from) \
393 : "memory"); \
394} while (0)
395
396#define __copy_user_zeroing(to,from,size) \
397do { \
398 int __d0, __d1; \
399 __asm__ __volatile__( \
400 "0: rep; movsl\n" \
401 " movl %3,%0\n" \
402 "1: rep; movsb\n" \
403 "2:\n" \
404 ".section .fixup,\"ax\"\n" \
405 "3: lea 0(%3,%0,4),%0\n" \
406 "4: pushl %0\n" \
407 " pushl %%eax\n" \
408 " xorl %%eax,%%eax\n" \
409 " rep; stosb\n" \
410 " popl %%eax\n" \
411 " popl %0\n" \
412 " jmp 2b\n" \
413 ".previous\n" \
414 ".section __ex_table,\"a\"\n" \
415 " .align 4\n" \
416 " .long 0b,3b\n" \
417 " .long 1b,4b\n" \
418 ".previous" \
419 : "=&c"(size), "=&D" (__d0), "=&S" (__d1) \
420 : "r"(size & 3), "0"(size / 4), "1"(to), "2"(from) \
421 : "memory"); \
422} while (0)
423
424
425
426
427static inline unsigned long
428__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
429{
430 __copy_user_zeroing(to,from,n);
431 return n;
432}
433
434static inline unsigned long
435__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
436{
437 __copy_user(to,from,n);
438 return n;
439}
440
441
442
443#define __constant_copy_user(to, from, size) \
444do { \
445 int __d0, __d1; \
446 switch (size & 3) { \
447 default: \
448 __asm__ __volatile__( \
449 "0: rep; movsl\n" \
450 "1:\n" \
451 ".section .fixup,\"ax\"\n" \
452 "2: shl $2,%0\n" \
453 " jmp 1b\n" \
454 ".previous\n" \
455 ".section __ex_table,\"a\"\n" \
456 " .align 4\n" \
457 " .long 0b,2b\n" \
458 ".previous" \
459 : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
460 : "1"(from), "2"(to), "0"(size/4) \
461 : "memory"); \
462 break; \
463 case 1: \
464 __asm__ __volatile__( \
465 "0: rep; movsl\n" \
466 "1: movsb\n" \
467 "2:\n" \
468 ".section .fixup,\"ax\"\n" \
469 "3: shl $2,%0\n" \
470 "4: incl %0\n" \
471 " jmp 2b\n" \
472 ".previous\n" \
473 ".section __ex_table,\"a\"\n" \
474 " .align 4\n" \
475 " .long 0b,3b\n" \
476 " .long 1b,4b\n" \
477 ".previous" \
478 : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
479 : "1"(from), "2"(to), "0"(size/4) \
480 : "memory"); \
481 break; \
482 case 2: \
483 __asm__ __volatile__( \
484 "0: rep; movsl\n" \
485 "1: movsw\n" \
486 "2:\n" \
487 ".section .fixup,\"ax\"\n" \
488 "3: shl $2,%0\n" \
489 "4: addl $2,%0\n" \
490 " jmp 2b\n" \
491 ".previous\n" \
492 ".section __ex_table,\"a\"\n" \
493 " .align 4\n" \
494 " .long 0b,3b\n" \
495 " .long 1b,4b\n" \
496 ".previous" \
497 : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
498 : "1"(from), "2"(to), "0"(size/4) \
499 : "memory"); \
500 break; \
501 case 3: \
502 __asm__ __volatile__( \
503 "0: rep; movsl\n" \
504 "1: movsw\n" \
505 "2: movsb\n" \
506 "3:\n" \
507 ".section .fixup,\"ax\"\n" \
508 "4: shl $2,%0\n" \
509 "5: addl $2,%0\n" \
510 "6: incl %0\n" \
511 " jmp 3b\n" \
512 ".previous\n" \
513 ".section __ex_table,\"a\"\n" \
514 " .align 4\n" \
515 " .long 0b,4b\n" \
516 " .long 1b,5b\n" \
517 " .long 2b,6b\n" \
518 ".previous" \
519 : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
520 : "1"(from), "2"(to), "0"(size/4) \
521 : "memory"); \
522 break; \
523 } \
524} while (0)
525
526
527#define __constant_copy_user_zeroing(to, from, size) \
528do { \
529 int __d0, __d1; \
530 switch (size & 3) { \
531 default: \
532 __asm__ __volatile__( \
533 "0: rep; movsl\n" \
534 "1:\n" \
535 ".section .fixup,\"ax\"\n" \
536 "2: pushl %0\n" \
537 " pushl %%eax\n" \
538 " xorl %%eax,%%eax\n" \
539 " rep; stosl\n" \
540 " popl %%eax\n" \
541 " popl %0\n" \
542 " shl $2,%0\n" \
543 " jmp 1b\n" \
544 ".previous\n" \
545 ".section __ex_table,\"a\"\n" \
546 " .align 4\n" \
547 " .long 0b,2b\n" \
548 ".previous" \
549 : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
550 : "1"(from), "2"(to), "0"(size/4) \
551 : "memory"); \
552 break; \
553 case 1: \
554 __asm__ __volatile__( \
555 "0: rep; movsl\n" \
556 "1: movsb\n" \
557 "2:\n" \
558 ".section .fixup,\"ax\"\n" \
559 "3: pushl %0\n" \
560 " pushl %%eax\n" \
561 " xorl %%eax,%%eax\n" \
562 " rep; stosl\n" \
563 " stosb\n" \
564 " popl %%eax\n" \
565 " popl %0\n" \
566 " shl $2,%0\n" \
567 " incl %0\n" \
568 " jmp 2b\n" \
569 "4: pushl %%eax\n" \
570 " xorl %%eax,%%eax\n" \
571 " stosb\n" \
572 " popl %%eax\n" \
573 " incl %0\n" \
574 " jmp 2b\n" \
575 ".previous\n" \
576 ".section __ex_table,\"a\"\n" \
577 " .align 4\n" \
578 " .long 0b,3b\n" \
579 " .long 1b,4b\n" \
580 ".previous" \
581 : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
582 : "1"(from), "2"(to), "0"(size/4) \
583 : "memory"); \
584 break; \
585 case 2: \
586 __asm__ __volatile__( \
587 "0: rep; movsl\n" \
588 "1: movsw\n" \
589 "2:\n" \
590 ".section .fixup,\"ax\"\n" \
591 "3: pushl %0\n" \
592 " pushl %%eax\n" \
593 " xorl %%eax,%%eax\n" \
594 " rep; stosl\n" \
595 " stosw\n" \
596 " popl %%eax\n" \
597 " popl %0\n" \
598 " shl $2,%0\n" \
599 " addl $2,%0\n" \
600 " jmp 2b\n" \
601 "4: pushl %%eax\n" \
602 " xorl %%eax,%%eax\n" \
603 " stosw\n" \
604 " popl %%eax\n" \
605 " addl $2,%0\n" \
606 " jmp 2b\n" \
607 ".previous\n" \
608 ".section __ex_table,\"a\"\n" \
609 " .align 4\n" \
610 " .long 0b,3b\n" \
611 " .long 1b,4b\n" \
612 ".previous" \
613 : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
614 : "1"(from), "2"(to), "0"(size/4) \
615 : "memory"); \
616 break; \
617 case 3: \
618 __asm__ __volatile__( \
619 "0: rep; movsl\n" \
620 "1: movsw\n" \
621 "2: movsb\n" \
622 "3:\n" \
623 ".section .fixup,\"ax\"\n" \
624 "4: pushl %0\n" \
625 " pushl %%eax\n" \
626 " xorl %%eax,%%eax\n" \
627 " rep; stosl\n" \
628 " stosw\n" \
629 " stosb\n" \
630 " popl %%eax\n" \
631 " popl %0\n" \
632 " shl $2,%0\n" \
633 " addl $3,%0\n" \
634 " jmp 2b\n" \
635 "5: pushl %%eax\n" \
636 " xorl %%eax,%%eax\n" \
637 " stosw\n" \
638 " stosb\n" \
639 " popl %%eax\n" \
640 " addl $3,%0\n" \
641 " jmp 2b\n" \
642 "6: pushl %%eax\n" \
643 " xorl %%eax,%%eax\n" \
644 " stosb\n" \
645 " popl %%eax\n" \
646 " incl %0\n" \
647 " jmp 3b\n" \
648 ".previous\n" \
649 ".section __ex_table,\"a\"\n" \
650 " .align 4\n" \
651 " .long 0b,4b\n" \
652 " .long 1b,5b\n" \
653 " .long 2b,6b\n" \
654 ".previous" \
655 : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
656 : "1"(from), "2"(to), "0"(size/4) \
657 : "memory"); \
658 break; \
659 } \
660} while (0)
661
662unsigned long __generic_copy_to_user(void *, const void *, unsigned long);
663unsigned long __generic_copy_from_user(void *, const void *, unsigned long);
664
665static inline unsigned long
666__constant_copy_to_user(void *to, const void *from, unsigned long n)
667{
668 prefetch(from);
669 if (access_ok(VERIFY_WRITE, to, n))
670 __constant_copy_user(to,from,n);
671 return n;
672}
673
674static inline unsigned long
675__constant_copy_from_user(void *to, const void *from, unsigned long n)
676{
677 if (access_ok(VERIFY_READ, from, n))
678 __constant_copy_user_zeroing(to,from,n);
679 else
680 memset(to, 0, n);
681 return n;
682}
683
684static inline unsigned long
685__constant_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
686{
687 __constant_copy_user(to,from,n);
688 return n;
689}
690
691static inline unsigned long
692__constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
693{
694 __constant_copy_user_zeroing(to,from,n);
695 return n;
696}
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711#define copy_to_user(to,from,n) \
712 (__builtin_constant_p(n) ? \
713 __constant_copy_to_user((to),(from),(n)) : \
714 __generic_copy_to_user((to),(from),(n)))
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732#define copy_from_user(to,from,n) \
733 (__builtin_constant_p(n) ? \
734 __constant_copy_from_user((to),(from),(n)) : \
735 __generic_copy_from_user((to),(from),(n)))
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751#define __copy_to_user(to,from,n) \
752 (__builtin_constant_p(n) ? \
753 __constant_copy_to_user_nocheck((to),(from),(n)) : \
754 __generic_copy_to_user_nocheck((to),(from),(n)))
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773#define __copy_from_user(to,from,n) \
774 (__builtin_constant_p(n) ? \
775 __constant_copy_from_user_nocheck((to),(from),(n)) : \
776 __generic_copy_from_user_nocheck((to),(from),(n)))
777
778long strncpy_from_user(char *dst, const char *src, long count);
779long __strncpy_from_user(char *dst, const char *src, long count);
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
796
797long strnlen_user(const char *str, long n);
798unsigned long clear_user(void *mem, unsigned long len);
799unsigned long __clear_user(void *mem, unsigned long len);
800
801#endif
802