Merge branches 'fixes', 'misc' and 'spectre' into for-next
[sfrench/cifs-2.6.git] / arch / arm / include / asm / uaccess.h
index 5451e1f05a193c002f3b30af921975a28c232833..c136eef8f690be60bba14f6a871dff286a5942f0 100644 (file)
@@ -69,6 +69,14 @@ extern int __put_user_bad(void);
 static inline void set_fs(mm_segment_t fs)
 {
        current_thread_info()->addr_limit = fs;
+
+       /*
+        * Prevent a mispredicted conditional call to set_fs from forwarding
+        * the wrong address limit to access_ok under speculation.
+        */
+       dsb(nsh);
+       isb();
+
        modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
 }
 
@@ -91,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
@@ -362,6 +396,14 @@ do {                                                                       \
        __pu_err;                                                       \
 })
 
+#ifdef CONFIG_CPU_SPECTRE
+/*
+ * When mitigating Spectre variant 1.1, all accessors need to include
+ * verification of the address space.
+ */
+#define __put_user(x, ptr) put_user(x, ptr)
+
+#else
 #define __put_user(x, ptr)                                             \
 ({                                                                     \
        long __pu_err = 0;                                              \
@@ -369,12 +411,6 @@ do {                                                                       \
        __pu_err;                                                       \
 })
 
-#define __put_user_error(x, ptr, err)                                  \
-({                                                                     \
-       __put_user_switch((x), (ptr), (err), __put_user_nocheck);       \
-       (void) 0;                                                       \
-})
-
 #define __put_user_nocheck(x, __pu_ptr, __err, __size)                 \
        do {                                                            \
                unsigned long __pu_addr = (unsigned long)__pu_ptr;      \
@@ -454,6 +490,7 @@ do {                                                                        \
        : "r" (x), "i" (-EFAULT)                                \
        : "cc")
 
+#endif /* !CONFIG_CPU_SPECTRE */
 
 #ifdef CONFIG_MMU
 extern unsigned long __must_check