X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fasm-i386%2Fuaccess.h;h=371457b1ceb6de2b47e8fcf7d125f8e57488cfb5;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=3553bec125f4488f82d7fb271b990ba731046856;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index 3553bec12..371457b1c 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -83,29 +83,6 @@ extern struct movsl_mask { */ #define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0)) -/** - * verify_area: - Obsolete, use access_ok() - * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE - * @addr: User space pointer to start of block to check - * @size: Size of block to check - * - * Context: User context only. This function may sleep. - * - * This function has been replaced by access_ok(). - * - * Checks if a pointer to a block of memory in user space is valid. - * - * Returns zero if the memory block may be valid, -EFAULT - * if it is definitely invalid. - * - * See access_ok() for more details. - */ -static inline int verify_area(int type, const void __user * addr, unsigned long size) -{ - return access_ok(type,addr,size) ? 0 : -EFAULT; -} - - /* * The exception table consists of pairs of addresses: the first is the * address of an instruction that is allowed to fault, and the second is @@ -170,7 +147,8 @@ extern void __get_user_4(void); * On error, the variable @x is set to zero. */ #define get_user(x,ptr) \ -({ int __ret_gu,__val_gu; \ +({ int __ret_gu; \ + unsigned long __val_gu; \ __chk_user_ptr(ptr); \ switch(sizeof (*(ptr))) { \ case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \ @@ -184,6 +162,21 @@ extern void __get_user_4(void); extern void __put_user_bad(void); +/* + * Strange magic calling convention: pointer in %ecx, + * value in %eax(:%edx), return value in %eax, no clobbers. + */ +extern void __put_user_1(void); +extern void __put_user_2(void); +extern void __put_user_4(void); +extern void __put_user_8(void); + +#define __put_user_1(x, ptr) __asm__ __volatile__("call __put_user_1":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr)) +#define __put_user_2(x, ptr) __asm__ __volatile__("call __put_user_2":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr)) +#define __put_user_4(x, ptr) __asm__ __volatile__("call __put_user_4":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr)) +#define __put_user_8(x, ptr) __asm__ __volatile__("call __put_user_8":"=a" (__ret_pu):"A" ((typeof(*(ptr)))(x)), "c" (ptr)) +#define __put_user_X(x, ptr) __asm__ __volatile__("call __put_user_X":"=a" (__ret_pu):"c" (ptr)) + /** * put_user: - Write a simple value into user space. * @x: Value to copy to user space. @@ -200,10 +193,38 @@ extern void __put_user_bad(void); * * Returns zero on success, or -EFAULT on error. */ -#define put_user(x,ptr) \ - __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) +#ifdef CONFIG_X86_WP_WORKS_OK + +#define put_user(x,ptr) \ +({ int __ret_pu; \ + __typeof__(*(ptr)) __pu_val; \ + __chk_user_ptr(ptr); \ + __pu_val = x; \ + switch(sizeof(*(ptr))) { \ + case 1: __put_user_1(__pu_val, ptr); break; \ + case 2: __put_user_2(__pu_val, ptr); break; \ + case 4: __put_user_4(__pu_val, ptr); break; \ + case 8: __put_user_8(__pu_val, ptr); break; \ + default:__put_user_X(__pu_val, ptr); break; \ + } \ + __ret_pu; \ +}) + +#else +#define put_user(x,ptr) \ +({ \ + int __ret_pu; \ + __typeof__(*(ptr)) __pus_tmp = x; \ + __ret_pu=0; \ + if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, \ + sizeof(*(ptr))) != 0)) \ + __ret_pu=-EFAULT; \ + __ret_pu; \ + }) +#endif + /** * __get_user: - Get a simple variable from user space, with less checking. * @x: Variable to store result. @@ -258,16 +279,6 @@ extern void __put_user_bad(void); }) -#define __put_user_check(x,ptr,size) \ -({ \ - long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ - might_sleep(); \ - if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ - __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \ - __pu_err; \ -}) - #define __put_user_u64(x, addr, err) \ __asm__ __volatile__( \ "1: movl %%eax,0(%2)\n" \ @@ -313,7 +324,7 @@ do { \ #endif struct __large_struct { unsigned long buf[100]; }; -#define __m(x) (*(struct __large_struct *)(x)) +#define __m(x) (*(struct __large_struct __user *)(x)) /* * Tell gcc we read from memory instead of writing: this is because @@ -338,7 +349,8 @@ struct __large_struct { unsigned long buf[100]; }; #define __get_user_nocheck(x,ptr,size) \ ({ \ - long __gu_err, __gu_val; \ + long __gu_err; \ + unsigned long __gu_val; \ __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\ (x) = (__typeof__(*(ptr)))__gu_val; \ __gu_err; \ @@ -401,7 +413,7 @@ unsigned long __must_check __copy_from_user_ll(void *to, * Returns number of bytes that could not be copied. * On success, this will be zero. */ -static inline unsigned long __must_check +static __always_inline unsigned long __must_check __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) { if (__builtin_constant_p(n)) { @@ -422,7 +434,7 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) return __copy_to_user_ll(to, from, n); } -static inline unsigned long __must_check +static __always_inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) { might_sleep(); @@ -446,7 +458,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) * If some data could not be copied, this function will pad the copied * data to the requested size using zero bytes. */ -static inline unsigned long +static __always_inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { if (__builtin_constant_p(n)) { @@ -467,7 +479,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) return __copy_from_user_ll(to, from, n); } -static inline unsigned long +static __always_inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { might_sleep();