X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=include%2Fasm-ia64%2Fuaccess.h;h=68f0e1deefe8fd57617c779c6770802aee5b4ed1;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=31d60e5e77909de57a3db9c29a4085d3c10369cd;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h index 31d60e5e7..68f0e1dee 100644 --- a/include/asm-ia64/uaccess.h +++ b/include/asm-ia64/uaccess.h @@ -60,14 +60,17 @@ * address TASK_SIZE is never valid. We also need to make sure that the address doesn't * point inside the virtually mapped linear page table. */ -#define __access_ok(addr, size, segment) \ - (likely((unsigned long) (addr) <= (segment).seg) \ - && ((segment).seg == KERNEL_DS.seg \ - || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))) +#define __access_ok(addr, size, segment) \ +({ \ + __chk_user_ptr(addr); \ + (likely((unsigned long) (addr) <= (segment).seg) \ + && ((segment).seg == KERNEL_DS.seg \ + || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))); \ +}) #define access_ok(type, addr, size) __access_ok((addr), (size), get_fs()) static inline int -verify_area (int type, const void *addr, unsigned long size) +verify_area (int type, const void __user *addr, unsigned long size) { return access_ok(type, addr, size) ? 0 : -EFAULT; } @@ -91,6 +94,42 @@ verify_area (int type, const void *addr, unsigned long size) #define __put_user(x, ptr) __put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr))) #define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr))) +extern long __put_user_unaligned_unknown (void); + +#define __put_user_unaligned(x, ptr) \ +({ \ + long __ret; \ + switch (sizeof(*(ptr))) { \ + case 1: __ret = __put_user((x), (ptr)); break; \ + case 2: __ret = (__put_user((x), (u8 __user *)(ptr))) \ + | (__put_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break; \ + case 4: __ret = (__put_user((x), (u16 __user *)(ptr))) \ + | (__put_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break; \ + case 8: __ret = (__put_user((x), (u32 __user *)(ptr))) \ + | (__put_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break; \ + default: __ret = __put_user_unaligned_unknown(); \ + } \ + __ret; \ +}) + +extern long __get_user_unaligned_unknown (void); + +#define __get_user_unaligned(x, ptr) \ +({ \ + long __ret; \ + switch (sizeof(*(ptr))) { \ + case 1: __ret = __get_user((x), (ptr)); break; \ + case 2: __ret = (__get_user((x), (u8 __user *)(ptr))) \ + | (__get_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break; \ + case 4: __ret = (__get_user((x), (u16 __user *)(ptr))) \ + | (__get_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break; \ + case 8: __ret = (__get_user((x), (u32 __user *)(ptr))) \ + | (__get_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break; \ + default: __ret = __get_user_unaligned_unknown(); \ + } \ + __ret; \ +}) + #ifdef ASM_SUPPORTED struct __large_struct { unsigned long buf[100]; }; # define __m(x) (*(struct __large_struct *)(x)) @@ -149,11 +188,11 @@ extern void __get_user_unknown (void); */ #define __do_get_user(check, x, ptr, size, segment) \ ({ \ - const __typeof__(*(ptr)) *__gu_ptr = (ptr); \ + const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ __typeof__ (size) __gu_size = (size); \ long __gu_err = -EFAULT, __gu_val = 0; \ \ - if (!check || __access_ok((long) __gu_ptr, size, segment)) \ + if (!check || __access_ok(__gu_ptr, size, segment)) \ switch (__gu_size) { \ case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break; \ case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break; \ @@ -177,11 +216,11 @@ extern void __put_user_unknown (void); #define __do_put_user(check, x, ptr, size, segment) \ ({ \ __typeof__ (x) __pu_x = (x); \ - __typeof__ (*(ptr)) *__pu_ptr = (ptr); \ + __typeof__ (*(ptr)) __user *__pu_ptr = (ptr); \ __typeof__ (size) __pu_size = (size); \ long __pu_err = -EFAULT; \ \ - if (!check || __access_ok((long) __pu_ptr, __pu_size, segment)) \ + if (!check || __access_ok(__pu_ptr, __pu_size, segment)) \ switch (__pu_size) { \ case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break; \ case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break; \ @@ -198,43 +237,64 @@ extern void __put_user_unknown (void); /* * Complex access routines */ -extern unsigned long __copy_user (void *to, const void *from, unsigned long count); +extern unsigned long __must_check __copy_user (void __user *to, const void __user *from, + unsigned long count); + +static inline unsigned long +__copy_to_user (void __user *to, const void *from, unsigned long count) +{ + return __copy_user(to, (void __user *) from, count); +} -#define __copy_to_user(to, from, n) __copy_user((to), (from), (n)) -#define __copy_from_user(to, from, n) __copy_user((to), (from), (n)) +static inline unsigned long +__copy_from_user (void *to, const void __user *from, unsigned long count) +{ + return __copy_user((void __user *) to, from, count); +} -#define copy_to_user(to, from, n) __copy_tofrom_user((to), (from), (n), 1) -#define copy_from_user(to, from, n) __copy_tofrom_user((to), (from), (n), 0) +#define __copy_to_user_inatomic __copy_to_user +#define __copy_from_user_inatomic __copy_from_user +#define copy_to_user(to, from, n) \ +({ \ + void __user *__cu_to = (to); \ + const void *__cu_from = (from); \ + long __cu_len = (n); \ + \ + if (__access_ok(__cu_to, __cu_len, get_fs())) \ + __cu_len = __copy_user(__cu_to, (void __user *) __cu_from, __cu_len); \ + __cu_len; \ +}) -#define __copy_tofrom_user(to, from, n, check_to) \ +#define copy_from_user(to, from, n) \ ({ \ void *__cu_to = (to); \ - const void *__cu_from = (from); \ + const void __user *__cu_from = (from); \ long __cu_len = (n); \ \ - if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs())) \ - __cu_len = __copy_user(__cu_to, __cu_from, __cu_len); \ + __chk_user_ptr(__cu_from); \ + if (__access_ok(__cu_from, __cu_len, get_fs())) \ + __cu_len = __copy_user((void __user *) __cu_to, __cu_from, __cu_len); \ __cu_len; \ }) #define __copy_in_user(to, from, size) __copy_user((to), (from), (size)) static inline unsigned long -copy_in_user (void *to, const void *from, unsigned long n) +copy_in_user (void __user *to, const void __user *from, unsigned long n) { if (likely(access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n))) n = __copy_user(to, from, n); return n; } -extern unsigned long __do_clear_user (void *, unsigned long); +extern unsigned long __do_clear_user (void __user *, unsigned long); #define __clear_user(to, n) __do_clear_user(to, n) #define clear_user(to, n) \ ({ \ unsigned long __cu_len = (n); \ - if (__access_ok((long) to, __cu_len, get_fs())) \ + if (__access_ok(to, __cu_len, get_fs())) \ __cu_len = __do_clear_user(to, __cu_len); \ __cu_len; \ }) @@ -244,25 +304,25 @@ extern unsigned long __do_clear_user (void *, unsigned long); * Returns: -EFAULT if exception before terminator, N if the entire buffer filled, else * strlen. */ -extern long __strncpy_from_user (char *to, const char *from, long to_len); +extern long __must_check __strncpy_from_user (char *to, const char __user *from, long to_len); #define strncpy_from_user(to, from, n) \ ({ \ - const char * __sfu_from = (from); \ + const char __user * __sfu_from = (from); \ long __sfu_ret = -EFAULT; \ - if (__access_ok((long) __sfu_from, 0, get_fs())) \ + if (__access_ok(__sfu_from, 0, get_fs())) \ __sfu_ret = __strncpy_from_user((to), __sfu_from, (n)); \ __sfu_ret; \ }) /* Returns: 0 if bad, string length+1 (memory size) of string if ok */ -extern unsigned long __strlen_user (const char *); +extern unsigned long __strlen_user (const char __user *); #define strlen_user(str) \ ({ \ - const char *__su_str = (str); \ + const char __user *__su_str = (str); \ unsigned long __su_ret = 0; \ - if (__access_ok((long) __su_str, 0, get_fs())) \ + if (__access_ok(__su_str, 0, get_fs())) \ __su_ret = __strlen_user(__su_str); \ __su_ret; \ }) @@ -272,13 +332,13 @@ extern unsigned long __strlen_user (const char *); * (N), a value greater than N if the limit would be exceeded, else * strlen. */ -extern unsigned long __strnlen_user (const char *, long); +extern unsigned long __strnlen_user (const char __user *, long); #define strnlen_user(str, len) \ ({ \ - const char *__su_str = (str); \ + const char __user *__su_str = (str); \ unsigned long __su_ret = 0; \ - if (__access_ok((long) __su_str, 0, get_fs())) \ + if (__access_ok(__su_str, 0, get_fs())) \ __su_ret = __strnlen_user(__su_str, len); \ __su_ret; \ })