diff options
Diffstat (limited to 'arch/x86/include/asm/uaccess.h')
-rw-r--r-- | arch/x86/include/asm/uaccess.h | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 8ec57c07b125..6f1bb74d547b 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h | |||
@@ -40,22 +40,30 @@ | |||
40 | /* | 40 | /* |
41 | * Test whether a block of memory is a valid user space address. | 41 | * Test whether a block of memory is a valid user space address. |
42 | * Returns 0 if the range is valid, nonzero otherwise. | 42 | * Returns 0 if the range is valid, nonzero otherwise. |
43 | * | ||
44 | * This is equivalent to the following test: | ||
45 | * (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64) | ||
46 | * | ||
47 | * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... | ||
48 | */ | 43 | */ |
44 | static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, unsigned long limit) | ||
45 | { | ||
46 | /* | ||
47 | * If we have used "sizeof()" for the size, | ||
48 | * we know it won't overflow the limit (but | ||
49 | * it might overflow the 'addr', so it's | ||
50 | * important to subtract the size from the | ||
51 | * limit, not add it to the address). | ||
52 | */ | ||
53 | if (__builtin_constant_p(size)) | ||
54 | return addr > limit - size; | ||
55 | |||
56 | /* Arbitrary sizes? Be careful about overflow */ | ||
57 | addr += size; | ||
58 | if (addr < size) | ||
59 | return true; | ||
60 | return addr > limit; | ||
61 | } | ||
49 | 62 | ||
50 | #define __range_not_ok(addr, size, limit) \ | 63 | #define __range_not_ok(addr, size, limit) \ |
51 | ({ \ | 64 | ({ \ |
52 | unsigned long flag, roksum; \ | ||
53 | __chk_user_ptr(addr); \ | 65 | __chk_user_ptr(addr); \ |
54 | asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \ | 66 | __chk_range_not_ok((unsigned long __force)(addr), size, limit); \ |
55 | : "=&r" (flag), "=r" (roksum) \ | ||
56 | : "1" (addr), "g" ((long)(size)), \ | ||
57 | "rm" (limit)); \ | ||
58 | flag; \ | ||
59 | }) | 67 | }) |
60 | 68 | ||
61 | /** | 69 | /** |
@@ -78,7 +86,7 @@ | |||
78 | * this function, memory access functions may still return -EFAULT. | 86 | * this function, memory access functions may still return -EFAULT. |
79 | */ | 87 | */ |
80 | #define access_ok(type, addr, size) \ | 88 | #define access_ok(type, addr, size) \ |
81 | (likely(__range_not_ok(addr, size, user_addr_max()) == 0)) | 89 | likely(!__range_not_ok(addr, size, user_addr_max())) |
82 | 90 | ||
83 | /* | 91 | /* |
84 | * The exception table consists of pairs of addresses relative to the | 92 | * The exception table consists of pairs of addresses relative to the |