|
@@ -99,6 +99,32 @@ static inline void set_fs(mm_segment_t fs)
|
|
|
#define __inttype(x) \
|
|
|
__typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
|
|
|
|
|
|
+/*
|
|
|
+ * Sanitise a uaccess pointer such that it becomes NULL if addr+size
|
|
|
+ * is above the current addr_limit.
|
|
|
+ */
|
|
|
+#define uaccess_mask_range_ptr(ptr, size) \
|
|
|
+ ((__typeof__(ptr))__uaccess_mask_range_ptr(ptr, size))
|
|
|
+static inline void __user *__uaccess_mask_range_ptr(const void __user *ptr,
|
|
|
+ size_t size)
|
|
|
+{
|
|
|
+ void __user *safe_ptr = (void __user *)ptr;
|
|
|
+ unsigned long tmp;
|
|
|
+
|
|
|
+ asm volatile(
|
|
|
+ " sub %1, %3, #1\n"
|
|
|
+ " subs %1, %1, %0\n"
|
|
|
+ " addhs %1, %1, #1\n"
|
|
|
+ " subhss %1, %1, %2\n"
|
|
|
+ " movlo %0, #0\n"
|
|
|
+ : "+r" (safe_ptr), "=&r" (tmp)
|
|
|
+ : "r" (size), "r" (current_thread_info()->addr_limit)
|
|
|
+ : "cc");
|
|
|
+
|
|
|
+ csdb();
|
|
|
+ return safe_ptr;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Single-value transfer routines. They automatically use the right
|
|
|
* size if we just have the right pointer type. Note that the functions
|