|
|
@@ -72,15 +72,15 @@ static inline void set_fs(mm_segment_t fs)
|
|
|
* This is equivalent to the following test:
|
|
|
* (u65)addr + (u65)size <= (u65)current->addr_limit + 1
|
|
|
*/
|
|
|
-static inline unsigned long __range_ok(unsigned long addr, unsigned long size)
|
|
|
+static inline unsigned long __range_ok(const void __user *addr, unsigned long size)
|
|
|
{
|
|
|
- unsigned long limit = current_thread_info()->addr_limit;
|
|
|
+ unsigned long ret, limit = current_thread_info()->addr_limit;
|
|
|
|
|
|
__chk_user_ptr(addr);
|
|
|
asm volatile(
|
|
|
// A + B <= C + 1 for all A,B,C, in four easy steps:
|
|
|
// 1: X = A + B; X' = X % 2^64
|
|
|
- " adds %0, %0, %2\n"
|
|
|
+ " adds %0, %3, %2\n"
|
|
|
// 2: Set C = 0 if X > 2^64, to guarantee X' > C in step 4
|
|
|
" csel %1, xzr, %1, hi\n"
|
|
|
// 3: Set X' = ~0 if X >= 2^64. For X == 2^64, this decrements X'
|
|
|
@@ -92,9 +92,9 @@ static inline unsigned long __range_ok(unsigned long addr, unsigned long size)
|
|
|
// testing X' - C == 0, subject to the previous adjustments.
|
|
|
" sbcs xzr, %0, %1\n"
|
|
|
" cset %0, ls\n"
|
|
|
- : "+r" (addr), "+r" (limit) : "Ir" (size) : "cc");
|
|
|
+ : "=&r" (ret), "+r" (limit) : "Ir" (size), "0" (addr) : "cc");
|
|
|
|
|
|
- return addr;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
@@ -104,7 +104,7 @@ static inline unsigned long __range_ok(unsigned long addr, unsigned long size)
|
|
|
*/
|
|
|
#define untagged_addr(addr) sign_extend64(addr, 55)
|
|
|
|
|
|
-#define access_ok(type, addr, size) __range_ok((unsigned long)(addr), size)
|
|
|
+#define access_ok(type, addr, size) __range_ok(addr, size)
|
|
|
#define user_addr_max get_fs
|
|
|
|
|
|
#define _ASM_EXTABLE(from, to) \
|