|
@@ -35,10 +35,7 @@
|
|
|
#include <asm/compiler.h>
|
|
|
#include <asm/extable.h>
|
|
|
|
|
|
-#define KERNEL_DS (-1UL)
|
|
|
#define get_ds() (KERNEL_DS)
|
|
|
-
|
|
|
-#define USER_DS TASK_SIZE_64
|
|
|
#define get_fs() (current_thread_info()->addr_limit)
|
|
|
|
|
|
static inline void set_fs(mm_segment_t fs)
|
|
@@ -66,22 +63,32 @@ static inline void set_fs(mm_segment_t fs)
|
|
|
* Returns 1 if the range is valid, 0 otherwise.
|
|
|
*
|
|
|
* This is equivalent to the following test:
|
|
|
- * (u65)addr + (u65)size <= current->addr_limit
|
|
|
- *
|
|
|
- * This needs 65-bit arithmetic.
|
|
|
+ * (u65)addr + (u65)size <= (u65)current->addr_limit + 1
|
|
|
*/
|
|
|
-#define __range_ok(addr, size) \
|
|
|
-({ \
|
|
|
- unsigned long __addr = (unsigned long)(addr); \
|
|
|
- unsigned long flag, roksum; \
|
|
|
- __chk_user_ptr(addr); \
|
|
|
- asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \
|
|
|
- : "=&r" (flag), "=&r" (roksum) \
|
|
|
- : "1" (__addr), "Ir" (size), \
|
|
|
- "r" (current_thread_info()->addr_limit) \
|
|
|
- : "cc"); \
|
|
|
- flag; \
|
|
|
-})
|
|
|
+static inline unsigned long __range_ok(unsigned long addr, unsigned long size)
|
|
|
+{
|
|
|
+ unsigned long 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"
|
|
|
+ // 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'
|
|
|
+ // to compensate for the carry flag being set in step 4. For
|
|
|
+ // X > 2^64, X' merely has to remain nonzero, which it does.
|
|
|
+ " csinv %0, %0, xzr, cc\n"
|
|
|
+ // 4: For X < 2^64, this gives us X' - C - 1 <= 0, where the -1
|
|
|
+ // comes from the carry in being clear. Otherwise, we are
|
|
|
+ // 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");
|
|
|
+
|
|
|
+ return addr;
|
|
|
+}
|
|
|
|
|
|
/*
|
|
|
* When dealing with data aborts, watchpoints, or instruction traps we may end
|
|
@@ -90,7 +97,7 @@ static inline void set_fs(mm_segment_t fs)
|
|
|
*/
|
|
|
#define untagged_addr(addr) sign_extend64(addr, 55)
|
|
|
|
|
|
-#define access_ok(type, addr, size) __range_ok(addr, size)
|
|
|
+#define access_ok(type, addr, size) __range_ok((unsigned long)(addr), size)
|
|
|
#define user_addr_max get_fs
|
|
|
|
|
|
#define _ASM_EXTABLE(from, to) \
|