diff options
Diffstat (limited to 'include/asm-arm/uaccess.h')
-rw-r--r-- | include/asm-arm/uaccess.h | 184 |
1 files changed, 100 insertions, 84 deletions
diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h index 064f0f5e8e2b..87aba57a66c4 100644 --- a/include/asm-arm/uaccess.h +++ b/include/asm-arm/uaccess.h | |||
@@ -41,15 +41,24 @@ struct exception_table_entry | |||
41 | extern int fixup_exception(struct pt_regs *regs); | 41 | extern int fixup_exception(struct pt_regs *regs); |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * These two are intentionally not defined anywhere - if the kernel | ||
45 | * code generates any references to them, that's a bug. | ||
46 | */ | ||
47 | extern int __get_user_bad(void); | ||
48 | extern int __put_user_bad(void); | ||
49 | |||
50 | /* | ||
44 | * Note that this is actually 0x1,0000,0000 | 51 | * Note that this is actually 0x1,0000,0000 |
45 | */ | 52 | */ |
46 | #define KERNEL_DS 0x00000000 | 53 | #define KERNEL_DS 0x00000000 |
47 | #define USER_DS TASK_SIZE | ||
48 | |||
49 | #define get_ds() (KERNEL_DS) | 54 | #define get_ds() (KERNEL_DS) |
55 | |||
56 | #ifdef CONFIG_MMU | ||
57 | |||
58 | #define USER_DS TASK_SIZE | ||
50 | #define get_fs() (current_thread_info()->addr_limit) | 59 | #define get_fs() (current_thread_info()->addr_limit) |
51 | 60 | ||
52 | static inline void set_fs (mm_segment_t fs) | 61 | static inline void set_fs(mm_segment_t fs) |
53 | { | 62 | { |
54 | current_thread_info()->addr_limit = fs; | 63 | current_thread_info()->addr_limit = fs; |
55 | modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); | 64 | modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); |
@@ -75,8 +84,6 @@ static inline void set_fs (mm_segment_t fs) | |||
75 | : "cc"); \ | 84 | : "cc"); \ |
76 | flag; }) | 85 | flag; }) |
77 | 86 | ||
78 | #define access_ok(type,addr,size) (__range_ok(addr,size) == 0) | ||
79 | |||
80 | /* | 87 | /* |
81 | * Single-value transfer routines. They automatically use the right | 88 | * Single-value transfer routines. They automatically use the right |
82 | * size if we just have the right pointer type. Note that the functions | 89 | * size if we just have the right pointer type. Note that the functions |
@@ -87,20 +94,10 @@ static inline void set_fs (mm_segment_t fs) | |||
87 | * fixup code, but there are a few places where it intrudes on the | 94 | * fixup code, but there are a few places where it intrudes on the |
88 | * main code path. When we only write to user space, there is no | 95 | * main code path. When we only write to user space, there is no |
89 | * problem. | 96 | * problem. |
90 | * | ||
91 | * The "__xxx" versions of the user access functions do not verify the | ||
92 | * address space - it must have been done previously with a separate | ||
93 | * "access_ok()" call. | ||
94 | * | ||
95 | * The "xxx_error" versions set the third argument to EFAULT if an | ||
96 | * error occurs, and leave it unchanged on success. Note that these | ||
97 | * versions are void (ie, don't return a value as such). | ||
98 | */ | 97 | */ |
99 | |||
100 | extern int __get_user_1(void *); | 98 | extern int __get_user_1(void *); |
101 | extern int __get_user_2(void *); | 99 | extern int __get_user_2(void *); |
102 | extern int __get_user_4(void *); | 100 | extern int __get_user_4(void *); |
103 | extern int __get_user_bad(void); | ||
104 | 101 | ||
105 | #define __get_user_x(__r2,__p,__e,__s,__i...) \ | 102 | #define __get_user_x(__r2,__p,__e,__s,__i...) \ |
106 | __asm__ __volatile__ ( \ | 103 | __asm__ __volatile__ ( \ |
@@ -131,6 +128,74 @@ extern int __get_user_bad(void); | |||
131 | __e; \ | 128 | __e; \ |
132 | }) | 129 | }) |
133 | 130 | ||
131 | extern int __put_user_1(void *, unsigned int); | ||
132 | extern int __put_user_2(void *, unsigned int); | ||
133 | extern int __put_user_4(void *, unsigned int); | ||
134 | extern int __put_user_8(void *, unsigned long long); | ||
135 | |||
136 | #define __put_user_x(__r2,__p,__e,__s) \ | ||
137 | __asm__ __volatile__ ( \ | ||
138 | __asmeq("%0", "r0") __asmeq("%2", "r2") \ | ||
139 | "bl __put_user_" #__s \ | ||
140 | : "=&r" (__e) \ | ||
141 | : "0" (__p), "r" (__r2) \ | ||
142 | : "ip", "lr", "cc") | ||
143 | |||
144 | #define put_user(x,p) \ | ||
145 | ({ \ | ||
146 | const register typeof(*(p)) __r2 asm("r2") = (x); \ | ||
147 | const register typeof(*(p)) __user *__p asm("r0") = (p);\ | ||
148 | register int __e asm("r0"); \ | ||
149 | switch (sizeof(*(__p))) { \ | ||
150 | case 1: \ | ||
151 | __put_user_x(__r2, __p, __e, 1); \ | ||
152 | break; \ | ||
153 | case 2: \ | ||
154 | __put_user_x(__r2, __p, __e, 2); \ | ||
155 | break; \ | ||
156 | case 4: \ | ||
157 | __put_user_x(__r2, __p, __e, 4); \ | ||
158 | break; \ | ||
159 | case 8: \ | ||
160 | __put_user_x(__r2, __p, __e, 8); \ | ||
161 | break; \ | ||
162 | default: __e = __put_user_bad(); break; \ | ||
163 | } \ | ||
164 | __e; \ | ||
165 | }) | ||
166 | |||
167 | #else /* CONFIG_MMU */ | ||
168 | |||
169 | /* | ||
170 | * uClinux has only one addr space, so has simplified address limits. | ||
171 | */ | ||
172 | #define USER_DS KERNEL_DS | ||
173 | |||
174 | #define segment_eq(a,b) (1) | ||
175 | #define __addr_ok(addr) (1) | ||
176 | #define __range_ok(addr,size) (0) | ||
177 | #define get_fs() (KERNEL_DS) | ||
178 | |||
179 | static inline void set_fs(mm_segment_t fs) | ||
180 | { | ||
181 | } | ||
182 | |||
183 | #define get_user(x,p) __get_user(x,p) | ||
184 | #define put_user(x,p) __put_user(x,p) | ||
185 | |||
186 | #endif /* CONFIG_MMU */ | ||
187 | |||
188 | #define access_ok(type,addr,size) (__range_ok(addr,size) == 0) | ||
189 | |||
190 | /* | ||
191 | * The "__xxx" versions of the user access functions do not verify the | ||
192 | * address space - it must have been done previously with a separate | ||
193 | * "access_ok()" call. | ||
194 | * | ||
195 | * The "xxx_error" versions set the third argument to EFAULT if an | ||
196 | * error occurs, and leave it unchanged on success. Note that these | ||
197 | * versions are void (ie, don't return a value as such). | ||
198 | */ | ||
134 | #define __get_user(x,ptr) \ | 199 | #define __get_user(x,ptr) \ |
135 | ({ \ | 200 | ({ \ |
136 | long __gu_err = 0; \ | 201 | long __gu_err = 0; \ |
@@ -212,43 +277,6 @@ do { \ | |||
212 | : "r" (addr), "i" (-EFAULT) \ | 277 | : "r" (addr), "i" (-EFAULT) \ |
213 | : "cc") | 278 | : "cc") |
214 | 279 | ||
215 | extern int __put_user_1(void *, unsigned int); | ||
216 | extern int __put_user_2(void *, unsigned int); | ||
217 | extern int __put_user_4(void *, unsigned int); | ||
218 | extern int __put_user_8(void *, unsigned long long); | ||
219 | extern int __put_user_bad(void); | ||
220 | |||
221 | #define __put_user_x(__r2,__p,__e,__s) \ | ||
222 | __asm__ __volatile__ ( \ | ||
223 | __asmeq("%0", "r0") __asmeq("%2", "r2") \ | ||
224 | "bl __put_user_" #__s \ | ||
225 | : "=&r" (__e) \ | ||
226 | : "0" (__p), "r" (__r2) \ | ||
227 | : "ip", "lr", "cc") | ||
228 | |||
229 | #define put_user(x,p) \ | ||
230 | ({ \ | ||
231 | const register typeof(*(p)) __r2 asm("r2") = (x); \ | ||
232 | const register typeof(*(p)) __user *__p asm("r0") = (p);\ | ||
233 | register int __e asm("r0"); \ | ||
234 | switch (sizeof(*(__p))) { \ | ||
235 | case 1: \ | ||
236 | __put_user_x(__r2, __p, __e, 1); \ | ||
237 | break; \ | ||
238 | case 2: \ | ||
239 | __put_user_x(__r2, __p, __e, 2); \ | ||
240 | break; \ | ||
241 | case 4: \ | ||
242 | __put_user_x(__r2, __p, __e, 4); \ | ||
243 | break; \ | ||
244 | case 8: \ | ||
245 | __put_user_x(__r2, __p, __e, 8); \ | ||
246 | break; \ | ||
247 | default: __e = __put_user_bad(); break; \ | ||
248 | } \ | ||
249 | __e; \ | ||
250 | }) | ||
251 | |||
252 | #define __put_user(x,ptr) \ | 280 | #define __put_user(x,ptr) \ |
253 | ({ \ | 281 | ({ \ |
254 | long __pu_err = 0; \ | 282 | long __pu_err = 0; \ |
@@ -353,66 +381,54 @@ do { \ | |||
353 | : "r" (x), "i" (-EFAULT) \ | 381 | : "r" (x), "i" (-EFAULT) \ |
354 | : "cc") | 382 | : "cc") |
355 | 383 | ||
356 | extern unsigned long __arch_copy_from_user(void *to, const void __user *from, unsigned long n); | 384 | |
357 | extern unsigned long __arch_copy_to_user(void __user *to, const void *from, unsigned long n); | 385 | #ifdef CONFIG_MMU |
358 | extern unsigned long __arch_clear_user(void __user *addr, unsigned long n); | 386 | extern unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n); |
359 | extern unsigned long __arch_strncpy_from_user(char *to, const char __user *from, unsigned long count); | 387 | extern unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n); |
360 | extern unsigned long __arch_strnlen_user(const char __user *s, long n); | 388 | extern unsigned long __clear_user(void __user *addr, unsigned long n); |
389 | #else | ||
390 | #define __copy_from_user(to,from,n) (memcpy(to, (void __force *)from, n), 0) | ||
391 | #define __copy_to_user(to,from,n) (memcpy((void __force *)to, from, n), 0) | ||
392 | #define __clear_user(addr,n) (memset((void __force *)addr, 0, n), 0) | ||
393 | #endif | ||
394 | |||
395 | extern unsigned long __strncpy_from_user(char *to, const char __user *from, unsigned long count); | ||
396 | extern unsigned long __strnlen_user(const char __user *s, long n); | ||
361 | 397 | ||
362 | static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) | 398 | static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) |
363 | { | 399 | { |
364 | if (access_ok(VERIFY_READ, from, n)) | 400 | if (access_ok(VERIFY_READ, from, n)) |
365 | n = __arch_copy_from_user(to, from, n); | 401 | n = __copy_from_user(to, from, n); |
366 | else /* security hole - plug it */ | 402 | else /* security hole - plug it */ |
367 | memzero(to, n); | 403 | memzero(to, n); |
368 | return n; | 404 | return n; |
369 | } | 405 | } |
370 | 406 | ||
371 | static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) | ||
372 | { | ||
373 | return __arch_copy_from_user(to, from, n); | ||
374 | } | ||
375 | |||
376 | static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) | 407 | static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) |
377 | { | 408 | { |
378 | if (access_ok(VERIFY_WRITE, to, n)) | 409 | if (access_ok(VERIFY_WRITE, to, n)) |
379 | n = __arch_copy_to_user(to, from, n); | 410 | n = __copy_to_user(to, from, n); |
380 | return n; | 411 | return n; |
381 | } | 412 | } |
382 | 413 | ||
383 | static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) | ||
384 | { | ||
385 | return __arch_copy_to_user(to, from, n); | ||
386 | } | ||
387 | |||
388 | #define __copy_to_user_inatomic __copy_to_user | 414 | #define __copy_to_user_inatomic __copy_to_user |
389 | #define __copy_from_user_inatomic __copy_from_user | 415 | #define __copy_from_user_inatomic __copy_from_user |
390 | 416 | ||
391 | static inline unsigned long clear_user (void __user *to, unsigned long n) | 417 | static inline unsigned long clear_user(void __user *to, unsigned long n) |
392 | { | 418 | { |
393 | if (access_ok(VERIFY_WRITE, to, n)) | 419 | if (access_ok(VERIFY_WRITE, to, n)) |
394 | n = __arch_clear_user(to, n); | 420 | n = __clear_user(to, n); |
395 | return n; | 421 | return n; |
396 | } | 422 | } |
397 | 423 | ||
398 | static inline unsigned long __clear_user (void __user *to, unsigned long n) | 424 | static inline long strncpy_from_user(char *dst, const char __user *src, long count) |
399 | { | ||
400 | return __arch_clear_user(to, n); | ||
401 | } | ||
402 | |||
403 | static inline long strncpy_from_user (char *dst, const char __user *src, long count) | ||
404 | { | 425 | { |
405 | long res = -EFAULT; | 426 | long res = -EFAULT; |
406 | if (access_ok(VERIFY_READ, src, 1)) | 427 | if (access_ok(VERIFY_READ, src, 1)) |
407 | res = __arch_strncpy_from_user(dst, src, count); | 428 | res = __strncpy_from_user(dst, src, count); |
408 | return res; | 429 | return res; |
409 | } | 430 | } |
410 | 431 | ||
411 | static inline long __strncpy_from_user (char *dst, const char __user *src, long count) | ||
412 | { | ||
413 | return __arch_strncpy_from_user(dst, src, count); | ||
414 | } | ||
415 | |||
416 | #define strlen_user(s) strnlen_user(s, ~0UL >> 1) | 432 | #define strlen_user(s) strnlen_user(s, ~0UL >> 1) |
417 | 433 | ||
418 | static inline long strnlen_user(const char __user *s, long n) | 434 | static inline long strnlen_user(const char __user *s, long n) |
@@ -420,7 +436,7 @@ static inline long strnlen_user(const char __user *s, long n) | |||
420 | unsigned long res = 0; | 436 | unsigned long res = 0; |
421 | 437 | ||
422 | if (__addr_ok(s)) | 438 | if (__addr_ok(s)) |
423 | res = __arch_strnlen_user(s, n); | 439 | res = __strnlen_user(s, n); |
424 | 440 | ||
425 | return res; | 441 | return res; |
426 | } | 442 | } |