Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.12-rc4 438 lines 12 kB view raw
1/* 2 * linux/include/asm-arm/uaccess.h 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8#ifndef _ASMARM_UACCESS_H 9#define _ASMARM_UACCESS_H 10 11/* 12 * User space memory access functions 13 */ 14#include <linux/sched.h> 15#include <asm/errno.h> 16#include <asm/memory.h> 17#include <asm/domain.h> 18#include <asm/system.h> 19 20#define VERIFY_READ 0 21#define VERIFY_WRITE 1 22 23/* 24 * The exception table consists of pairs of addresses: the first is the 25 * address of an instruction that is allowed to fault, and the second is 26 * the address at which the program should continue. No registers are 27 * modified, so it is entirely up to the continuation code to figure out 28 * what to do. 29 * 30 * All the routines below use bits of fixup code that are out of line 31 * with the main instruction path. This means when everything is well, 32 * we don't even have to jump over them. Further, they do not intrude 33 * on our cache or tlb entries. 34 */ 35 36struct exception_table_entry 37{ 38 unsigned long insn, fixup; 39}; 40 41extern int fixup_exception(struct pt_regs *regs); 42 43/* 44 * Note that this is actually 0x1,0000,0000 45 */ 46#define KERNEL_DS 0x00000000 47#define USER_DS TASK_SIZE 48 49#define get_ds() (KERNEL_DS) 50#define get_fs() (current_thread_info()->addr_limit) 51 52static inline void set_fs (mm_segment_t fs) 53{ 54 current_thread_info()->addr_limit = fs; 55 modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); 56} 57 58#define segment_eq(a,b) ((a) == (b)) 59 60#define __addr_ok(addr) ({ \ 61 unsigned long flag; \ 62 __asm__("cmp %2, %0; movlo %0, #0" \ 63 : "=&r" (flag) \ 64 : "0" (current_thread_info()->addr_limit), "r" (addr) \ 65 : "cc"); \ 66 (flag == 0); }) 67 68/* We use 33-bit arithmetic here... */ 69#define __range_ok(addr,size) ({ \ 70 unsigned long flag, sum; \ 71 __chk_user_ptr(addr); \ 72 __asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \ 73 : "=&r" (flag), "=&r" (sum) \ 74 : "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \ 75 : "cc"); \ 76 flag; }) 77 78#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) 79 80/* this function will go away soon - use access_ok() instead */ 81static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size) 82{ 83 return access_ok(type, addr, size) ? 0 : -EFAULT; 84} 85 86/* 87 * Single-value transfer routines. They automatically use the right 88 * size if we just have the right pointer type. Note that the functions 89 * which read from user space (*get_*) need to take care not to leak 90 * kernel data even if the calling code is buggy and fails to check 91 * the return value. This means zeroing out the destination variable 92 * or buffer on error. Normally this is done out of line by the 93 * fixup code, but there are a few places where it intrudes on the 94 * main code path. When we only write to user space, there is no 95 * problem. 96 * 97 * The "__xxx" versions of the user access functions do not verify the 98 * address space - it must have been done previously with a separate 99 * "access_ok()" call. 100 * 101 * The "xxx_error" versions set the third argument to EFAULT if an 102 * error occurs, and leave it unchanged on success. Note that these 103 * versions are void (ie, don't return a value as such). 104 */ 105 106extern int __get_user_1(void *); 107extern int __get_user_2(void *); 108extern int __get_user_4(void *); 109extern int __get_user_8(void *); 110extern int __get_user_bad(void); 111 112#define __get_user_x(__r2,__p,__e,__s,__i...) \ 113 __asm__ __volatile__ ( \ 114 __asmeq("%0", "r0") __asmeq("%1", "r2") \ 115 "bl __get_user_" #__s \ 116 : "=&r" (__e), "=r" (__r2) \ 117 : "0" (__p) \ 118 : __i, "cc") 119 120#define get_user(x,p) \ 121 ({ \ 122 const register typeof(*(p)) __user *__p asm("r0") = (p);\ 123 register typeof(*(p)) __r2 asm("r2"); \ 124 register int __e asm("r0"); \ 125 switch (sizeof(*(__p))) { \ 126 case 1: \ 127 __get_user_x(__r2, __p, __e, 1, "lr"); \ 128 break; \ 129 case 2: \ 130 __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ 131 break; \ 132 case 4: \ 133 __get_user_x(__r2, __p, __e, 4, "lr"); \ 134 break; \ 135 case 8: \ 136 __get_user_x(__r2, __p, __e, 8, "lr"); \ 137 break; \ 138 default: __e = __get_user_bad(); break; \ 139 } \ 140 x = __r2; \ 141 __e; \ 142 }) 143 144#define __get_user(x,ptr) \ 145({ \ 146 long __gu_err = 0; \ 147 __get_user_err((x),(ptr),__gu_err); \ 148 __gu_err; \ 149}) 150 151#define __get_user_error(x,ptr,err) \ 152({ \ 153 __get_user_err((x),(ptr),err); \ 154 (void) 0; \ 155}) 156 157#define __get_user_err(x,ptr,err) \ 158do { \ 159 unsigned long __gu_addr = (unsigned long)(ptr); \ 160 unsigned long __gu_val; \ 161 __chk_user_ptr(ptr); \ 162 switch (sizeof(*(ptr))) { \ 163 case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ 164 case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ 165 case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \ 166 default: (__gu_val) = __get_user_bad(); \ 167 } \ 168 (x) = (__typeof__(*(ptr)))__gu_val; \ 169} while (0) 170 171#define __get_user_asm_byte(x,addr,err) \ 172 __asm__ __volatile__( \ 173 "1: ldrbt %1,[%2],#0\n" \ 174 "2:\n" \ 175 " .section .fixup,\"ax\"\n" \ 176 " .align 2\n" \ 177 "3: mov %0, %3\n" \ 178 " mov %1, #0\n" \ 179 " b 2b\n" \ 180 " .previous\n" \ 181 " .section __ex_table,\"a\"\n" \ 182 " .align 3\n" \ 183 " .long 1b, 3b\n" \ 184 " .previous" \ 185 : "+r" (err), "=&r" (x) \ 186 : "r" (addr), "i" (-EFAULT) \ 187 : "cc") 188 189#ifndef __ARMEB__ 190#define __get_user_asm_half(x,__gu_addr,err) \ 191({ \ 192 unsigned long __b1, __b2; \ 193 __get_user_asm_byte(__b1, __gu_addr, err); \ 194 __get_user_asm_byte(__b2, __gu_addr + 1, err); \ 195 (x) = __b1 | (__b2 << 8); \ 196}) 197#else 198#define __get_user_asm_half(x,__gu_addr,err) \ 199({ \ 200 unsigned long __b1, __b2; \ 201 __get_user_asm_byte(__b1, __gu_addr, err); \ 202 __get_user_asm_byte(__b2, __gu_addr + 1, err); \ 203 (x) = (__b1 << 8) | __b2; \ 204}) 205#endif 206 207#define __get_user_asm_word(x,addr,err) \ 208 __asm__ __volatile__( \ 209 "1: ldrt %1,[%2],#0\n" \ 210 "2:\n" \ 211 " .section .fixup,\"ax\"\n" \ 212 " .align 2\n" \ 213 "3: mov %0, %3\n" \ 214 " mov %1, #0\n" \ 215 " b 2b\n" \ 216 " .previous\n" \ 217 " .section __ex_table,\"a\"\n" \ 218 " .align 3\n" \ 219 " .long 1b, 3b\n" \ 220 " .previous" \ 221 : "+r" (err), "=&r" (x) \ 222 : "r" (addr), "i" (-EFAULT) \ 223 : "cc") 224 225extern int __put_user_1(void *, unsigned int); 226extern int __put_user_2(void *, unsigned int); 227extern int __put_user_4(void *, unsigned int); 228extern int __put_user_8(void *, unsigned long long); 229extern int __put_user_bad(void); 230 231#define __put_user_x(__r2,__p,__e,__s) \ 232 __asm__ __volatile__ ( \ 233 __asmeq("%0", "r0") __asmeq("%2", "r2") \ 234 "bl __put_user_" #__s \ 235 : "=&r" (__e) \ 236 : "0" (__p), "r" (__r2) \ 237 : "ip", "lr", "cc") 238 239#define put_user(x,p) \ 240 ({ \ 241 const register typeof(*(p)) __r2 asm("r2") = (x); \ 242 const register typeof(*(p)) __user *__p asm("r0") = (p);\ 243 register int __e asm("r0"); \ 244 switch (sizeof(*(__p))) { \ 245 case 1: \ 246 __put_user_x(__r2, __p, __e, 1); \ 247 break; \ 248 case 2: \ 249 __put_user_x(__r2, __p, __e, 2); \ 250 break; \ 251 case 4: \ 252 __put_user_x(__r2, __p, __e, 4); \ 253 break; \ 254 case 8: \ 255 __put_user_x(__r2, __p, __e, 8); \ 256 break; \ 257 default: __e = __put_user_bad(); break; \ 258 } \ 259 __e; \ 260 }) 261 262#define __put_user(x,ptr) \ 263({ \ 264 long __pu_err = 0; \ 265 __put_user_err((x),(ptr),__pu_err); \ 266 __pu_err; \ 267}) 268 269#define __put_user_error(x,ptr,err) \ 270({ \ 271 __put_user_err((x),(ptr),err); \ 272 (void) 0; \ 273}) 274 275#define __put_user_err(x,ptr,err) \ 276do { \ 277 unsigned long __pu_addr = (unsigned long)(ptr); \ 278 __typeof__(*(ptr)) __pu_val = (x); \ 279 __chk_user_ptr(ptr); \ 280 switch (sizeof(*(ptr))) { \ 281 case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ 282 case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ 283 case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \ 284 case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \ 285 default: __put_user_bad(); \ 286 } \ 287} while (0) 288 289#define __put_user_asm_byte(x,__pu_addr,err) \ 290 __asm__ __volatile__( \ 291 "1: strbt %1,[%2],#0\n" \ 292 "2:\n" \ 293 " .section .fixup,\"ax\"\n" \ 294 " .align 2\n" \ 295 "3: mov %0, %3\n" \ 296 " b 2b\n" \ 297 " .previous\n" \ 298 " .section __ex_table,\"a\"\n" \ 299 " .align 3\n" \ 300 " .long 1b, 3b\n" \ 301 " .previous" \ 302 : "+r" (err) \ 303 : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \ 304 : "cc") 305 306#ifndef __ARMEB__ 307#define __put_user_asm_half(x,__pu_addr,err) \ 308({ \ 309 unsigned long __temp = (unsigned long)(x); \ 310 __put_user_asm_byte(__temp, __pu_addr, err); \ 311 __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \ 312}) 313#else 314#define __put_user_asm_half(x,__pu_addr,err) \ 315({ \ 316 unsigned long __temp = (unsigned long)(x); \ 317 __put_user_asm_byte(__temp >> 8, __pu_addr, err); \ 318 __put_user_asm_byte(__temp, __pu_addr + 1, err); \ 319}) 320#endif 321 322#define __put_user_asm_word(x,__pu_addr,err) \ 323 __asm__ __volatile__( \ 324 "1: strt %1,[%2],#0\n" \ 325 "2:\n" \ 326 " .section .fixup,\"ax\"\n" \ 327 " .align 2\n" \ 328 "3: mov %0, %3\n" \ 329 " b 2b\n" \ 330 " .previous\n" \ 331 " .section __ex_table,\"a\"\n" \ 332 " .align 3\n" \ 333 " .long 1b, 3b\n" \ 334 " .previous" \ 335 : "+r" (err) \ 336 : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \ 337 : "cc") 338 339#ifndef __ARMEB__ 340#define __reg_oper0 "%R2" 341#define __reg_oper1 "%Q2" 342#else 343#define __reg_oper0 "%Q2" 344#define __reg_oper1 "%R2" 345#endif 346 347#define __put_user_asm_dword(x,__pu_addr,err) \ 348 __asm__ __volatile__( \ 349 "1: strt " __reg_oper1 ", [%1], #4\n" \ 350 "2: strt " __reg_oper0 ", [%1], #0\n" \ 351 "3:\n" \ 352 " .section .fixup,\"ax\"\n" \ 353 " .align 2\n" \ 354 "4: mov %0, %3\n" \ 355 " b 3b\n" \ 356 " .previous\n" \ 357 " .section __ex_table,\"a\"\n" \ 358 " .align 3\n" \ 359 " .long 1b, 4b\n" \ 360 " .long 2b, 4b\n" \ 361 " .previous" \ 362 : "+r" (err), "+r" (__pu_addr) \ 363 : "r" (x), "i" (-EFAULT) \ 364 : "cc") 365 366extern unsigned long __arch_copy_from_user(void *to, const void __user *from, unsigned long n); 367extern unsigned long __arch_copy_to_user(void __user *to, const void *from, unsigned long n); 368extern unsigned long __arch_clear_user(void __user *addr, unsigned long n); 369extern unsigned long __arch_strncpy_from_user(char *to, const char __user *from, unsigned long count); 370extern unsigned long __arch_strnlen_user(const char __user *s, long n); 371 372static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) 373{ 374 if (access_ok(VERIFY_READ, from, n)) 375 n = __arch_copy_from_user(to, from, n); 376 else /* security hole - plug it */ 377 memzero(to, n); 378 return n; 379} 380 381static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) 382{ 383 return __arch_copy_from_user(to, from, n); 384} 385 386static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) 387{ 388 if (access_ok(VERIFY_WRITE, to, n)) 389 n = __arch_copy_to_user(to, from, n); 390 return n; 391} 392 393static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) 394{ 395 return __arch_copy_to_user(to, from, n); 396} 397 398#define __copy_to_user_inatomic __copy_to_user 399#define __copy_from_user_inatomic __copy_from_user 400 401static inline unsigned long clear_user (void __user *to, unsigned long n) 402{ 403 if (access_ok(VERIFY_WRITE, to, n)) 404 n = __arch_clear_user(to, n); 405 return n; 406} 407 408static inline unsigned long __clear_user (void __user *to, unsigned long n) 409{ 410 return __arch_clear_user(to, n); 411} 412 413static inline long strncpy_from_user (char *dst, const char __user *src, long count) 414{ 415 long res = -EFAULT; 416 if (access_ok(VERIFY_READ, src, 1)) 417 res = __arch_strncpy_from_user(dst, src, count); 418 return res; 419} 420 421static inline long __strncpy_from_user (char *dst, const char __user *src, long count) 422{ 423 return __arch_strncpy_from_user(dst, src, count); 424} 425 426#define strlen_user(s) strnlen_user(s, ~0UL >> 1) 427 428static inline long strnlen_user(const char __user *s, long n) 429{ 430 unsigned long res = 0; 431 432 if (__addr_ok(s)) 433 res = __arch_strnlen_user(s, n); 434 435 return res; 436} 437 438#endif /* _ASMARM_UACCESS_H */