Make it possible to override some functions from uaccess.h so that architectures with an mmu can provide assembly versions of the functions with their own fixup logic. Signed-off-by: Arnd Bergmann <arnd@xxxxxxxx> --- include/asm-generic/uaccess.h | 102 +++++++++++++++++++++++++--------------- 1 files changed, 64 insertions(+), 38 deletions(-) diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h index ebeacd9..e05f6a9 100644 --- a/include/asm-generic/uaccess.h +++ b/include/asm-generic/uaccess.h @@ -31,14 +31,14 @@ static inline void set_fs(mm_segment_t fs) #define VERIFY_READ 0 #define VERIFY_WRITE 1 -#define access_ok(type, addr, size) _access_ok((unsigned long)(addr),(size)) +#define access_ok(type, addr, size) __access_ok((unsigned long)(addr),(size)) /* * The architecture should really override this if possible, at least * doing a check on the get_fs() */ -#ifndef _access_ok -static inline int _access_ok(unsigned long addr, unsigned long size) +#ifndef __access_ok +static inline int __access_ok(unsigned long addr, unsigned long size) { return 1; } @@ -93,7 +93,7 @@ extern int __put_user_bad(void); #endif #define put_user(x, ptr) ( \ - access_ok(VERIFY_WRITE, ptr, sizeof (*ptr)) ? \ + __access_ok(ptr, sizeof (*ptr)) ? \ __put_user(x, ptr) : \ -EFAULT) @@ -120,45 +120,62 @@ extern int __get_user_bad(void); #endif #define get_user(x, ptr) ( \ - access_ok(VERIFY_READ, ptr, sizeof (*ptr)) ? \ + __access_ok(ptr, sizeof (*ptr)) ? \ __get_user(x, ptr) : \ -EFAULT) -#define __copy_from_user(to, from, n) (memcpy(to, from, n), 0) -#define __copy_to_user(to, from, n) (memcpy(to, from, n), 0) -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user +#ifndef __copy_from_user +static inline __must_check long __copy_from_user(void *to, + const void __user *from, unsigned long n) +{ + memcpy(to, (const void __force *)from, n); + return 0; +} +#endif -#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; }) +#ifndef __copy_to_user +static inline __must_check long __copy_to_user(void __user *to, + const void *from, unsigned long n) +{ + memcpy((void __force *)to, from, n); + return 0; +} +#endif + +#ifndef __copy_from_user_inatomic +#define __copy_from_user_inatomic __copy_from_user +#endif -#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; }) +#ifndef __copy_to_user_inatomic +#define __copy_to_user_inatomic __copy_to_user +#endif static inline long copy_from_user(void *to, - const void __user * from, unsigned long n) + const void __user * from, unsigned long n) { - if (access_ok(VERIFY_READ, from, n)) - __copy_from_user(to, from, n); + might_sleep(); + if (__access_ok(from, n)) + return __copy_from_user(to, from, n); else return n; - return 0; } -static inline long copy_to_user(void *to, - const void __user * from, unsigned long n) +static inline long copy_to_user(void __user *to, + const void *from, unsigned long n) { - if (access_ok(VERIFY_WRITE, to, n)) - __copy_to_user(to, from, n); + might_sleep(); + if (__access_ok(to, n)) + return __copy_to_user(to, from, n); else return n; - return 0; } /* * Copy a null terminated string from userspace. */ - +#ifndef __strncpy_from_user static inline long -__do_strncpy_from_user(char *dst, const char __user *src, long count) +__strncpy_from_user(char *dst, const char __user *src, long count) { char *tmp; strncpy(dst, src, count); @@ -166,19 +183,14 @@ __do_strncpy_from_user(char *dst, const char __user *src, long count) ; return (tmp - dst); } +#endif static inline long strncpy_from_user(char *dst, const char __user *src, long count) { - if (!access_ok(VERIFY_READ, src, 1)) + if (!__access_ok(src, 1)) return -EFAULT; - return __do_strncpy_from_user(dst, src, count); -} - -static inline long -__strncpy_from_user(char *dst, const char __user *src, long count) -{ - return __do_strncpy_from_user(dst, src, count); + return __strncpy_from_user(dst, src, count); } /* @@ -186,24 +198,38 @@ __strncpy_from_user(char *dst, const char __user *src, long count) * * Return 0 on exception, a value greater than N if too long */ -static inline long strnlen_user(const char *src, long n) +#ifndef strnlen_user +static inline long strnlen_user(const char __user *src, long n) { - return strlen(src) + 1; + return strlen((void * __force)src) + 1; } +#endif -#define strlen_user(str) strnlen_user(str, 32767) +static inline long strlen_user(const char __user *src) +{ + return strnlen_user(src, 32767); +} /* * Zero Userspace */ - -static inline unsigned long -__clear_user(void *to, unsigned long n) +#ifndef __clear_user +static inline __must_check unsigned long +__clear_user(void __user *to, unsigned long n) { - memset(to, 0, n); + memset((void __force *)to, 0, n); return 0; } +#endif -#define clear_user(to, n) __clear_user(to, n) +static inline __must_check unsigned long +clear_user(void __user *to, unsigned long n) +{ + might_sleep(); + if (!__access_ok(to, n)) + return n; + + return __clear_user(to, n); +} #endif /* __ASM_GENERIC_UACCESS_H */ -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-arch" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html