X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fasm-arm%2Fuaccess.h;h=064f0f5e8e2b9e3361082dbc420b2e6248263c40;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=87aba57a66c40d5b0f10fe199c3159fa5710a9e3;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h index 87aba57a6..064f0f5e8 100644 --- a/include/asm-arm/uaccess.h +++ b/include/asm-arm/uaccess.h @@ -40,25 +40,16 @@ struct exception_table_entry extern int fixup_exception(struct pt_regs *regs); -/* - * These two are intentionally not defined anywhere - if the kernel - * code generates any references to them, that's a bug. - */ -extern int __get_user_bad(void); -extern int __put_user_bad(void); - /* * Note that this is actually 0x1,0000,0000 */ #define KERNEL_DS 0x00000000 -#define get_ds() (KERNEL_DS) - -#ifdef CONFIG_MMU - #define USER_DS TASK_SIZE + +#define get_ds() (KERNEL_DS) #define get_fs() (current_thread_info()->addr_limit) -static inline void set_fs(mm_segment_t fs) +static inline void set_fs (mm_segment_t fs) { current_thread_info()->addr_limit = fs; modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); @@ -84,6 +75,8 @@ static inline void set_fs(mm_segment_t fs) : "cc"); \ flag; }) +#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) + /* * Single-value transfer routines. They automatically use the right * size if we just have the right pointer type. Note that the functions @@ -94,10 +87,20 @@ static inline void set_fs(mm_segment_t fs) * fixup code, but there are a few places where it intrudes on the * main code path. When we only write to user space, there is no * problem. + * + * The "__xxx" versions of the user access functions do not verify the + * address space - it must have been done previously with a separate + * "access_ok()" call. + * + * The "xxx_error" versions set the third argument to EFAULT if an + * error occurs, and leave it unchanged on success. Note that these + * versions are void (ie, don't return a value as such). */ + extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); +extern int __get_user_bad(void); #define __get_user_x(__r2,__p,__e,__s,__i...) \ __asm__ __volatile__ ( \ @@ -128,74 +131,6 @@ extern int __get_user_4(void *); __e; \ }) -extern int __put_user_1(void *, unsigned int); -extern int __put_user_2(void *, unsigned int); -extern int __put_user_4(void *, unsigned int); -extern int __put_user_8(void *, unsigned long long); - -#define __put_user_x(__r2,__p,__e,__s) \ - __asm__ __volatile__ ( \ - __asmeq("%0", "r0") __asmeq("%2", "r2") \ - "bl __put_user_" #__s \ - : "=&r" (__e) \ - : "0" (__p), "r" (__r2) \ - : "ip", "lr", "cc") - -#define put_user(x,p) \ - ({ \ - const register typeof(*(p)) __r2 asm("r2") = (x); \ - const register typeof(*(p)) __user *__p asm("r0") = (p);\ - register int __e asm("r0"); \ - switch (sizeof(*(__p))) { \ - case 1: \ - __put_user_x(__r2, __p, __e, 1); \ - break; \ - case 2: \ - __put_user_x(__r2, __p, __e, 2); \ - break; \ - case 4: \ - __put_user_x(__r2, __p, __e, 4); \ - break; \ - case 8: \ - __put_user_x(__r2, __p, __e, 8); \ - break; \ - default: __e = __put_user_bad(); break; \ - } \ - __e; \ - }) - -#else /* CONFIG_MMU */ - -/* - * uClinux has only one addr space, so has simplified address limits. - */ -#define USER_DS KERNEL_DS - -#define segment_eq(a,b) (1) -#define __addr_ok(addr) (1) -#define __range_ok(addr,size) (0) -#define get_fs() (KERNEL_DS) - -static inline void set_fs(mm_segment_t fs) -{ -} - -#define get_user(x,p) __get_user(x,p) -#define put_user(x,p) __put_user(x,p) - -#endif /* CONFIG_MMU */ - -#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) - -/* - * The "__xxx" versions of the user access functions do not verify the - * address space - it must have been done previously with a separate - * "access_ok()" call. - * - * The "xxx_error" versions set the third argument to EFAULT if an - * error occurs, and leave it unchanged on success. Note that these - * versions are void (ie, don't return a value as such). - */ #define __get_user(x,ptr) \ ({ \ long __gu_err = 0; \ @@ -277,6 +212,43 @@ do { \ : "r" (addr), "i" (-EFAULT) \ : "cc") +extern int __put_user_1(void *, unsigned int); +extern int __put_user_2(void *, unsigned int); +extern int __put_user_4(void *, unsigned int); +extern int __put_user_8(void *, unsigned long long); +extern int __put_user_bad(void); + +#define __put_user_x(__r2,__p,__e,__s) \ + __asm__ __volatile__ ( \ + __asmeq("%0", "r0") __asmeq("%2", "r2") \ + "bl __put_user_" #__s \ + : "=&r" (__e) \ + : "0" (__p), "r" (__r2) \ + : "ip", "lr", "cc") + +#define put_user(x,p) \ + ({ \ + const register typeof(*(p)) __r2 asm("r2") = (x); \ + const register typeof(*(p)) __user *__p asm("r0") = (p);\ + register int __e asm("r0"); \ + switch (sizeof(*(__p))) { \ + case 1: \ + __put_user_x(__r2, __p, __e, 1); \ + break; \ + case 2: \ + __put_user_x(__r2, __p, __e, 2); \ + break; \ + case 4: \ + __put_user_x(__r2, __p, __e, 4); \ + break; \ + case 8: \ + __put_user_x(__r2, __p, __e, 8); \ + break; \ + default: __e = __put_user_bad(); break; \ + } \ + __e; \ + }) + #define __put_user(x,ptr) \ ({ \ long __pu_err = 0; \ @@ -381,54 +353,66 @@ do { \ : "r" (x), "i" (-EFAULT) \ : "cc") - -#ifdef CONFIG_MMU -extern unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n); -extern unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n); -extern unsigned long __clear_user(void __user *addr, unsigned long n); -#else -#define __copy_from_user(to,from,n) (memcpy(to, (void __force *)from, n), 0) -#define __copy_to_user(to,from,n) (memcpy((void __force *)to, from, n), 0) -#define __clear_user(addr,n) (memset((void __force *)addr, 0, n), 0) -#endif - -extern unsigned long __strncpy_from_user(char *to, const char __user *from, unsigned long count); -extern unsigned long __strnlen_user(const char __user *s, long n); +extern unsigned long __arch_copy_from_user(void *to, const void __user *from, unsigned long n); +extern unsigned long __arch_copy_to_user(void __user *to, const void *from, unsigned long n); +extern unsigned long __arch_clear_user(void __user *addr, unsigned long n); +extern unsigned long __arch_strncpy_from_user(char *to, const char __user *from, unsigned long count); +extern unsigned long __arch_strnlen_user(const char __user *s, long n); static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) - n = __copy_from_user(to, from, n); + n = __arch_copy_from_user(to, from, n); else /* security hole - plug it */ memzero(to, n); return n; } +static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) +{ + return __arch_copy_from_user(to, from, n); +} + static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - n = __copy_to_user(to, from, n); + n = __arch_copy_to_user(to, from, n); return n; } +static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) +{ + return __arch_copy_to_user(to, from, n); +} + #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user -static inline unsigned long clear_user(void __user *to, unsigned long n) +static inline unsigned long clear_user (void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - n = __clear_user(to, n); + n = __arch_clear_user(to, n); return n; } -static inline long strncpy_from_user(char *dst, const char __user *src, long count) +static inline unsigned long __clear_user (void __user *to, unsigned long n) +{ + return __arch_clear_user(to, n); +} + +static inline long strncpy_from_user (char *dst, const char __user *src, long count) { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) - res = __strncpy_from_user(dst, src, count); + res = __arch_strncpy_from_user(dst, src, count); return res; } +static inline long __strncpy_from_user (char *dst, const char __user *src, long count) +{ + return __arch_strncpy_from_user(dst, src, count); +} + #define strlen_user(s) strnlen_user(s, ~0UL >> 1) static inline long strnlen_user(const char __user *s, long n) @@ -436,7 +420,7 @@ static inline long strnlen_user(const char __user *s, long n) unsigned long res = 0; if (__addr_ok(s)) - res = __strnlen_user(s, n); + res = __arch_strnlen_user(s, n); return res; }