]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
UBUNTU: SAUCE: asm-generic/barrier: add generic nospec helpers
authorMark Rutland <mark.rutland@arm.com>
Thu, 7 Dec 2017 17:14:24 +0000 (17:14 +0000)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Mon, 5 Feb 2018 17:23:05 +0000 (18:23 +0100)
CVE-2017-5754 ARM64 KPTI fixes

Under speculation, CPUs may mis-predict branches in bounds checks. Thus,
memory accesses under a bounds check may be speculated even if the
bounds check fails, providing a primitive for building a side channel.

This patch adds helpers which can be used to inhibit the use of
out-of-bounds pointers and/or valeus read from these under speculation.

A generic implementation is provided for compatibility, but does not
guarantee safety under speculation. Architectures are expected to
override these helpers as necessary.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Acked-by: Brad Figg <brad.figg@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
include/asm-generic/barrier.h

index ad5fcfaf6e14d4a2a123ba54eaf626c86da1d502..bbd426ee551879f323dae8f2a5f3be088541488a 100644 (file)
 #define read_barrier_depends()         do { } while (0)
 #endif
 
+/**
+ * nospec_ptr() - Ensure a  pointer is bounded, even under speculation.
+ *
+ * @ptr: the pointer to test
+ * @lo: the lower valid bound for @ptr, inclusive
+ * @hi: the upper valid bound for @ptr, exclusive
+ *
+ * If @ptr falls in the interval [@lo, @i), returns @ptr, otherwise returns
+ * NULL.
+ *
+ * Architectures should override this to ensure that ptr falls in the [lo, hi)
+ * interval both under architectural execution and under speculation,
+ * preventing propagation of an out-of-bounds pointer to code which is
+ * speculatively executed.
+ */
+#ifndef nospec_ptr
+#define nospec_ptr(ptr, lo, hi)                                                \
+({                                                                     \
+       typeof (ptr) __ptr = (ptr);                                     \
+       typeof (ptr) __lo = (lo);                                       \
+       typeof (ptr) __hi = (hi);                                       \
+                                                                       \
+       (__lo <= __ptr && __ptr < __hi) ? __ptr : NULL;                 \
+})
+#endif
+
+/**
+ * nospec_load() - Load a pointer, respecting bounds under speculation
+ *
+ * @ptr: the pointer to load
+ * @lo: the lower valid bound for @ptr, inclusive
+ * @hi: the upper valid bound for @ptr, exclusive
+ *
+ * If @ptr falls in the interval [@lo, @hi), returns the value at @ptr,
+ * otherwise returns (typeof(*ptr))0.
+ *
+ * Architectures should override this to ensure that ptr falls in the [lo, hi)
+ * interval both under architectural execution and under speculation,
+ * preventing speculative out-of-bounds reads.
+ */
+#ifndef nospec_load
+#define nospec_load(ptr, lo, hi)                                       \
+({                                                                     \
+       typeof (ptr) __ptr = (ptr);                                     \
+       typeof (ptr) __lo = (lo);                                       \
+       typeof (ptr) __hi = (hi);                                       \
+                                                                       \
+       (__lo <= __ptr && __ptr <= __hi) ?                              \
+               *__ptr :                                                \
+               (typeof(*__ptr))(unsigned long)0;                       \
+})
+#endif
+
+/**
+ * nospec_array_load - Load an array entry, respecting bounds under speculation
+ *
+ * @arr: the base of the array
+ * @idx: the index of the element to load
+ * @sz: the number of elements in the array
+ *
+ * If @idx falls in the interval [0, @sz), returns the value at @arr[@idx],
+ * otherwise returns (typeof(*ptr))0.
+ *
+ * This is a wrapper around nospec_load(), provided for convenience.
+ * Architectures should implement nospec_load() to ensure this is the case
+ * under speculation.
+ */
+#define nospec_array_load(arr, idx, sz)                                        \
+({                                                                     \
+       typeof(*(arr)) *__arr = arr;                                    \
+       typeof(idx) __idx = idx;                                        \
+       typeof(sz) __sz = __sz;                                         \
+                                                                       \
+       nospec_load(__arr + __idx, __arr, __arr + __sz);                \
+})
+
 #ifndef __smp_mb
 #define __smp_mb()     mb()
 #endif