|
40 | 40 | /*
|
41 | 41 | * Test whether a block of memory is a valid user space address.
|
42 | 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 int __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 | + return (addr < size) || (addr > limit); |
| 59 | +} |
49 | 60 |
|
50 | 61 | #define __range_not_ok(addr, size, limit) \
|
51 | 62 | ({ \
|
52 |
| - unsigned long flag, roksum; \ |
53 | 63 | __chk_user_ptr(addr); \
|
54 |
| - asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \ |
55 |
| - : "=&r" (flag), "=r" (roksum) \ |
56 |
| - : "1" (addr), "g" ((long)(size)), \ |
57 |
| - "rm" (limit)); \ |
58 |
| - flag; \ |
| 64 | + __chk_range_not_ok((unsigned long __force)(addr), size, limit); \ |
59 | 65 | })
|
60 | 66 |
|
61 | 67 | /**
|
|
0 commit comments