diff options
Diffstat (limited to 'arch/microblaze/include/asm/uaccess.h')
| -rw-r--r-- | arch/microblaze/include/asm/uaccess.h | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 072b0077abf..0aa005703a0 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h @@ -80,7 +80,7 @@ extern unsigned long search_exception_table(unsigned long); static inline int ___range_ok(unsigned long addr, unsigned long size) { return ((addr < memory_start) || - ((addr + size) > memory_end)); + ((addr + size - 1) > (memory_start + memory_size - 1))); } #define __range_ok(addr, size) \ @@ -90,17 +90,25 @@ static inline int ___range_ok(unsigned long addr, unsigned long size) #else -/* - * Address is valid if: - * - "addr", "addr + size" and "size" are all below the limit - */ -#define access_ok(type, addr, size) \ - (get_fs().seg >= (((unsigned long)(addr)) | \ - (size) | ((unsigned long)(addr) + (size)))) - -/* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n", - type?"WRITE":"READ",addr,size,get_fs().seg)) */ - +static inline int access_ok(int type, const void __user *addr, + unsigned long size) +{ + if (!size) + goto ok; + + if ((get_fs().seg < ((unsigned long)addr)) || + (get_fs().seg < ((unsigned long)addr + size - 1))) { + pr_debug("ACCESS fail: %s at 0x%08x (size 0x%x), seg 0x%08x\n", + type ? "WRITE" : "READ ", (__force u32)addr, (u32)size, + (u32)get_fs().seg); + return 0; + } +ok: + pr_debug("ACCESS OK: %s at 0x%08x (size 0x%x), seg 0x%08x\n", + type ? "WRITE" : "READ ", (__force u32)addr, (u32)size, + (u32)get_fs().seg); + return 1; +} #endif #ifdef CONFIG_MMU @@ -108,7 +116,7 @@ static inline int ___range_ok(unsigned long addr, unsigned long size) # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n" #else # define __FIXUP_SECTION ".section .discard,\"ax\"\n" -# define __EX_TABLE_SECTION ".section .discard,\"a\"\n" +# define __EX_TABLE_SECTION ".section .discard,\"ax\"\n" #endif extern unsigned long __copy_tofrom_user(void __user *to, @@ -137,7 +145,7 @@ static inline unsigned long __must_check __clear_user(void __user *to, static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) { - might_sleep(); + might_fault(); if (unlikely(!access_ok(VERIFY_WRITE, to, n))) return n; @@ -298,11 +306,10 @@ extern long __user_bad(void); #define __put_user_check(x, ptr, size) \ ({ \ - typeof(*(ptr)) __pu_val; \ + typeof(*(ptr)) volatile __pu_val = x; \ typeof(*(ptr)) __user *__pu_addr = (ptr); \ int __pu_err = 0; \ \ - __pu_val = (x); \ if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \ switch (size) { \ case 1: \ @@ -364,7 +371,7 @@ extern long __user_bad(void); static inline long copy_from_user(void *to, const void __user *from, unsigned long n) { - might_sleep(); + might_fault(); if (access_ok(VERIFY_READ, from, n)) return __copy_from_user(to, from, n); return n; @@ -378,7 +385,7 @@ static inline long copy_from_user(void *to, static inline long copy_to_user(void __user *to, const void *from, unsigned long n) { - might_sleep(); + might_fault(); if (access_ok(VERIFY_WRITE, to, n)) return __copy_to_user(to, from, n); return n; |
