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 <asm/page.h>
12
13#define VERIFY_READ 0
14#define VERIFY_WRITE 1
15
16
17
18
19
20
21
22
23
24#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
25
26
27#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
28#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
29
30#define get_ds() (KERNEL_DS)
31#define get_fs() (current_thread_info()->addr_limit)
32#define set_fs(x) (current_thread_info()->addr_limit = (x))
33
34#define segment_eq(a,b) ((a).seg == (b).seg)
35
36
37
38
39#ifdef CONFIG_X86_INTEL_USERCOPY
40extern struct movsl_mask {
41 int mask;
42} ____cacheline_aligned_in_smp movsl_mask;
43#endif
44
45int __verify_write(const void *, unsigned long);
46
47#define __addr_ok(addr) ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
48
49
50
51
52#define __range_ok(addr,size) ({ \
53 unsigned long flag,sum; \
54 asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
55 :"=&r" (flag), "=r" (sum) \
56 :"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \
57 flag; })
58
59#ifdef CONFIG_X86_WP_WORKS_OK
60
61#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
62
63#else
64
65#define access_ok(type,addr,size) ( (__range_ok(addr,size) == 0) && \
66 ((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || \
67 __verify_write((void *)(addr),(size))))
68
69#endif
70
71static inline int verify_area(int type, const void * addr, unsigned long size)
72{
73 return access_ok(type,addr,size) ? 0 : -EFAULT;
74}
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90struct exception_table_entry
91{
92 unsigned long insn, fixup;
93};
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110extern void __get_user_1(void);
111extern void __get_user_2(void);
112extern void __get_user_4(void);
113
114#define __get_user_x(size,ret,x,ptr) \
115 __asm__ __volatile__("call __get_user_" #size \
116 :"=a" (ret),"=d" (x) \
117 :"0" (ptr))
118
119
120#define get_user(x,ptr) \
121({ int __ret_gu,__val_gu; \
122 switch(sizeof (*(ptr))) { \
123 case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
124 case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
125 case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break; \
126 default: __get_user_x(X,__ret_gu,__val_gu,ptr); break; \
127 } \
128 (x) = (__typeof__(*(ptr)))__val_gu; \
129 __ret_gu; \
130})
131
132extern void __put_user_1(void);
133extern void __put_user_2(void);
134extern void __put_user_4(void);
135extern void __put_user_8(void);
136
137extern void __put_user_bad(void);
138
139#define put_user(x,ptr) \
140 __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
141
142#define __get_user(x,ptr) \
143 __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
144#define __put_user(x,ptr) \
145 __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
146
147#define __put_user_nocheck(x,ptr,size) \
148({ \
149 long __pu_err; \
150 __put_user_size((x),(ptr),(size),__pu_err); \
151 __pu_err; \
152})
153
154
155#define __put_user_check(x,ptr,size) \
156({ \
157 long __pu_err = -EFAULT; \
158 __typeof__(*(ptr)) *__pu_addr = (ptr); \
159 if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
160 __put_user_size((x),__pu_addr,(size),__pu_err); \
161 __pu_err; \
162})
163
164#define __put_user_u64(x, addr, err) \
165 __asm__ __volatile__( \
166 "1: movl %%eax,0(%2)\n" \
167 "2: movl %%edx,4(%2)\n" \
168 "3:\n" \
169 ".section .fixup,\"ax\"\n" \
170 "4: movl %3,%0\n" \
171 " jmp 3b\n" \
172 ".previous\n" \
173 ".section __ex_table,\"a\"\n" \
174 " .align 4\n" \
175 " .long 1b,4b\n" \
176 " .long 2b,4b\n" \
177 ".previous" \
178 : "=r"(err) \
179 : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
180
181#define __put_user_size(x,ptr,size,retval) \
182do { \
183 retval = 0; \
184 switch (size) { \
185 case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break; \
186 case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break; \
187 case 4: __put_user_asm(x,ptr,retval,"l","","ir"); break; \
188 case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break; \
189 default: __put_user_bad(); \
190 } \
191} while (0)
192
193struct __large_struct { unsigned long buf[100]; };
194#define __m(x) (*(struct __large_struct *)(x))
195
196
197
198
199
200
201#define __put_user_asm(x, addr, err, itype, rtype, ltype) \
202 __asm__ __volatile__( \
203 "1: mov"itype" %"rtype"1,%2\n" \
204 "2:\n" \
205 ".section .fixup,\"ax\"\n" \
206 "3: movl %3,%0\n" \
207 " jmp 2b\n" \
208 ".previous\n" \
209 ".section __ex_table,\"a\"\n" \
210 " .align 4\n" \
211 " .long 1b,3b\n" \
212 ".previous" \
213 : "=r"(err) \
214 : ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err))
215
216
217#define __get_user_nocheck(x,ptr,size) \
218({ \
219 long __gu_err, __gu_val; \
220 __get_user_size(__gu_val,(ptr),(size),__gu_err); \
221 (x) = (__typeof__(*(ptr)))__gu_val; \
222 __gu_err; \
223})
224
225extern long __get_user_bad(void);
226
227#define __get_user_size(x,ptr,size,retval) \
228do { \
229 retval = 0; \
230 switch (size) { \
231 case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break; \
232 case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break; \
233 case 4: __get_user_asm(x,ptr,retval,"l","","=r"); break; \
234 default: (x) = __get_user_bad(); \
235 } \
236} while (0)
237
238#define __get_user_asm(x, addr, err, itype, rtype, ltype) \
239 __asm__ __volatile__( \
240 "1: mov"itype" %2,%"rtype"1\n" \
241 "2:\n" \
242 ".section .fixup,\"ax\"\n" \
243 "3: movl %3,%0\n" \
244 " xor"itype" %"rtype"1,%"rtype"1\n" \
245 " jmp 2b\n" \
246 ".previous\n" \
247 ".section __ex_table,\"a\"\n" \
248 " .align 4\n" \
249 " .long 1b,3b\n" \
250 ".previous" \
251 : "=r"(err), ltype (x) \
252 : "m"(__m(addr)), "i"(-EFAULT), "0"(err))
253
254
255unsigned long copy_to_user(void *to, const void *from, unsigned long n);
256unsigned long copy_from_user(void *to, const void *from, unsigned long n);
257unsigned long __copy_to_user(void *to, const void *from, unsigned long n);
258unsigned long __copy_from_user(void *to, const void *from, unsigned long n);
259
260long strncpy_from_user(char *dst, const char *src, long count);
261long __strncpy_from_user(char *dst, const char *src, long count);
262#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
263long strnlen_user(const char *str, long n);
264unsigned long clear_user(void *mem, unsigned long len);
265unsigned long __clear_user(void *mem, unsigned long len);
266
267#endif
268