3593c5f
From 1d115042dde79e3c0fcc18af548342b172e749e1 Mon Sep 17 00:00:00 2001
3593c5f
From: Mark Rutland <mark.rutland@arm.com>
3593c5f
Date: Thu, 7 Dec 2017 17:14:24 +0000
3593c5f
Subject: [PATCH 01/19] asm-generic/barrier: add generic nospec helpers
3593c5f
3593c5f
Under speculation, CPUs may mis-predict branches in bounds checks. Thus,
3593c5f
memory accesses under a bounds check may be speculated even if the
3593c5f
bounds check fails, providing a primitive for building a side channel.
3593c5f
3593c5f
This patch adds helpers which can be used to inhibit the use of
3593c5f
out-of-bounds pointers under speculation.
3593c5f
3593c5f
A generic implementation is provided for compatibility, but does not
3593c5f
guarantee safety under speculation. Architectures are expected to
3593c5f
override these helpers as necessary.
3593c5f
3593c5f
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
3593c5f
Signed-off-by: Will Deacon <will.deacon@arm.com>
3593c5f
Cc: Daniel Willams <dan.j.williams@intel.com>
3593c5f
Cc: Peter Zijlstra <peterz@infradead.org>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 include/asm-generic/barrier.h | 68 +++++++++++++++++++++++++++++++++++++++++++
3593c5f
 1 file changed, 68 insertions(+)
3593c5f
3593c5f
diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
3593c5f
index fe297b599b0a..91c3071f49e5 100644
3593c5f
--- a/include/asm-generic/barrier.h
3593c5f
+++ b/include/asm-generic/barrier.h
3593c5f
@@ -54,6 +54,74 @@
3593c5f
 #define read_barrier_depends()		do { } while (0)
3593c5f
 #endif
3593c5f
3593c5f
+/*
3593c5f
+ * Inhibit subsequent speculative memory accesses.
3593c5f
+ *
3593c5f
+ * Architectures with a suitable memory barrier should provide an
3593c5f
+ * implementation. This is non-portable, and generic code should use
3593c5f
+ * nospec_ptr().
3593c5f
+ */
3593c5f
+#ifndef __nospec_barrier
3593c5f
+#define __nospec_barrier()		do { } while (0)
3593c5f
+#endif
3593c5f
+
3593c5f
+/**
3593c5f
+ * nospec_ptr() - Ensure a  pointer is bounded, even under speculation.
3593c5f
+ *
3593c5f
+ * @ptr: the pointer to test
3593c5f
+ * @lo: the lower valid bound for @ptr, inclusive
3593c5f
+ * @hi: the upper valid bound for @ptr, exclusive
3593c5f
+ *
3593c5f
+ * If @ptr falls in the interval [@lo, @i), returns @ptr, otherwise returns
3593c5f
+ * NULL.
3593c5f
+ *
3593c5f
+ * Architectures which do not provide __nospec_barrier() should override this
3593c5f
+ * to ensure that ptr falls in the [lo, hi) interval both under architectural
3593c5f
+ * execution and under speculation, preventing propagation of an out-of-bounds
3593c5f
+ * pointer to code which is speculatively executed.
3593c5f
+ */
3593c5f
+#ifndef nospec_ptr
3593c5f
+#define nospec_ptr(ptr, lo, hi)						\
3593c5f
+({									\
3593c5f
+	typeof (ptr) __ret;						\
3593c5f
+	typeof (ptr) __ptr = (ptr);					\
3593c5f
+	typeof (ptr) __lo = (lo);					\
3593c5f
+	typeof (ptr) __hi = (hi);					\
3593c5f
+									\
3593c5f
+	__ret = (__lo <= __ptr && __ptr < __hi) ? __ptr : NULL;		\
3593c5f
+									\
3593c5f
+	__nospec_barrier();						\
3593c5f
+									\
3593c5f
+	__ret;								\
3593c5f
+})
3593c5f
+#endif
3593c5f
+
3593c5f
+/**
3593c5f
+ * nospec_array_ptr - Generate a pointer to an array element, ensuring the
3593c5f
+ * pointer is bounded under speculation.
3593c5f
+ *
3593c5f
+ * @arr: the base of the array
3593c5f
+ * @idx: the index of the element
3593c5f
+ * @sz: the number of elements in the array
3593c5f
+ *
3593c5f
+ * If @idx falls in the interval [0, @sz), returns the pointer to @arr[@idx],
3593c5f
+ * otherwise returns NULL.
3593c5f
+ *
3593c5f
+ * This is a wrapper around nospec_ptr(), provided for convenience.
3593c5f
+ * Architectures should implement nospec_ptr() to ensure this is the case
3593c5f
+ * under speculation.
3593c5f
+ */
3593c5f
+#define nospec_array_ptr(arr, idx, sz)					\
3593c5f
+({									\
3593c5f
+	typeof(*(arr)) *__arr = (arr);					\
3593c5f
+	typeof(idx) __idx = (idx);					\
3593c5f
+	typeof(sz) __sz = (sz);						\
3593c5f
+									\
3593c5f
+	nospec_ptr(__arr + __idx, __arr, __arr + __sz);			\
3593c5f
+})
3593c5f
+
3593c5f
+#undef __nospec_barrier
3593c5f
+
3593c5f
 #ifndef __smp_mb
3593c5f
 #define __smp_mb()	mb()
3593c5f
 #endif
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From 0a9659964052448903985b38f08b3912ab65f1a9 Mon Sep 17 00:00:00 2001
3593c5f
From: Mark Rutland <mark.rutland@arm.com>
3593c5f
Date: Wed, 3 Jan 2018 19:47:06 +0000
3593c5f
Subject: [PATCH 02/19] Documentation: document nospec helpers
3593c5f
3593c5f
Document the rationale and usage of the new nospec*() helpers.
3593c5f
3593c5f
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
3593c5f
Signed-off-by: Will Deacon <will.deacon@arm.com>
3593c5f
Cc: Dan Williams <dan.j.williams@intel.com>
3593c5f
Cc: Jonathan Corbet <corbet@lwn.net>
3593c5f
Cc: Peter Zijlstra <peterz@infradead.org>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 Documentation/speculation.txt | 166 ++++++++++++++++++++++++++++++++++++++++++
3593c5f
 1 file changed, 166 insertions(+)
3593c5f
 create mode 100644 Documentation/speculation.txt
3593c5f
3593c5f
diff --git a/Documentation/speculation.txt b/Documentation/speculation.txt
3593c5f
new file mode 100644
3593c5f
index 000000000000..748fcd4dcda4
3593c5f
--- /dev/null
3593c5f
+++ b/Documentation/speculation.txt
3593c5f
@@ -0,0 +1,166 @@
3593c5f
+This document explains potential effects of speculation, and how undesirable
3593c5f
+effects can be mitigated portably using common APIs.
3593c5f
+
3593c5f
+===========
3593c5f
+Speculation
3593c5f
+===========
3593c5f
+
3593c5f
+To improve performance and minimize average latencies, many contemporary CPUs
3593c5f
+employ speculative execution techniques such as branch prediction, performing
3593c5f
+work which may be discarded at a later stage.
3593c5f
+
3593c5f
+Typically speculative execution cannot be observed from architectural state,
3593c5f
+such as the contents of registers. However, in some cases it is possible to
3593c5f
+observe its impact on microarchitectural state, such as the presence or
3593c5f
+absence of data in caches. Such state may form side-channels which can be
3593c5f
+observed to extract secret information.
3593c5f
+
3593c5f
+For example, in the presence of branch prediction, it is possible for bounds
3593c5f
+checks to be ignored by code which is speculatively executed. Consider the
3593c5f
+following code:
3593c5f
+
3593c5f
+	int load_array(int *array, unsigned int idx) {
3593c5f
+		if (idx >= MAX_ARRAY_ELEMS)
3593c5f
+			return 0;
3593c5f
+		else
3593c5f
+			return array[idx];
3593c5f
+	}
3593c5f
+
3593c5f
+Which, on arm64, may be compiled to an assembly sequence such as:
3593c5f
+
3593c5f
+	CMP	<idx>, #MAX_ARRAY_ELEMS
3593c5f
+	B.LT	less
3593c5f
+	MOV	<returnval>, #0
3593c5f
+	RET
3593c5f
+  less:
3593c5f
+	LDR	<returnval>, [<array>, <idx>]
3593c5f
+	RET
3593c5f
+
3593c5f
+It is possible that a CPU mis-predicts the conditional branch, and
3593c5f
+speculatively loads array[idx], even if idx >= MAX_ARRAY_ELEMS. This value
3593c5f
+will subsequently be discarded, but the speculated load may affect
3593c5f
+microarchitectural state which can be subsequently measured.
3593c5f
+
3593c5f
+More complex sequences involving multiple dependent memory accesses may result
3593c5f
+in sensitive information being leaked. Consider the following code, building on
3593c5f
+the prior example:
3593c5f
+
3593c5f
+	int load_dependent_arrays(int *arr1, int *arr2, int idx) {
3593c5f
+		int val1, val2,
3593c5f
+
3593c5f
+		val1 = load_array(arr1, idx);
3593c5f
+		val2 = load_array(arr2, val1);
3593c5f
+
3593c5f
+		return val2;
3593c5f
+	}
3593c5f
+
3593c5f
+Under speculation, the first call to load_array() may return the value of an
3593c5f
+out-of-bounds address, while the second call will influence microarchitectural
3593c5f
+state dependent on this value. This may provide an arbitrary read primitive.
3593c5f
+
3593c5f
+====================================
3593c5f
+Mitigating speculation side-channels
3593c5f
+====================================
3593c5f
+
3593c5f
+The kernel provides a generic API to ensure that bounds checks are respected
3593c5f
+even under speculation. Architectures which are affected by speculation-based
3593c5f
+side-channels are expected to implement these primitives.
3593c5f
+
3593c5f
+The following helpers found in <asm/barrier.h> can be used to prevent
3593c5f
+information from being leaked via side-channels.
3593c5f
+
3593c5f
+* nospec_ptr(ptr, lo, hi)
3593c5f
+
3593c5f
+  Returns a sanitized pointer that is bounded by the [lo, hi) interval. When
3593c5f
+  ptr < lo, or ptr >= hi, NULL is returned. Prevents an out-of-bounds pointer
3593c5f
+  being propagated to code which is speculatively executed.
3593c5f
+
3593c5f
+  This is expected to be used by code which computes pointers to data
3593c5f
+  structures, where part of the address (such as an array index) may be
3593c5f
+  user-controlled.
3593c5f
+
3593c5f
+  This can be used to protect the earlier load_array() example:
3593c5f
+
3593c5f
+  int load_array(int *array, unsigned int idx)
3593c5f
+  {
3593c5f
+	int *elem;
3593c5f
+
3593c5f
+	if ((elem = nospec_ptr(array + idx, array, array + MAX_ARRAY_ELEMS)))
3593c5f
+		return *elem;
3593c5f
+	else
3593c5f
+		return 0;
3593c5f
+  }
3593c5f
+
3593c5f
+  This can also be used in situations where multiple fields on a structure are
3593c5f
+  accessed:
3593c5f
+
3593c5f
+	struct foo array[SIZE];
3593c5f
+	int a, b;
3593c5f
+
3593c5f
+	void do_thing(int idx)
3593c5f
+	{
3593c5f
+		struct foo *elem;
3593c5f
+
3593c5f
+		if ((elem = nospec_ptr(array + idx, array, array + SIZE)) {
3593c5f
+			a = elem->field_a;
3593c5f
+			b = elem->field_b;
3593c5f
+		}
3593c5f
+	}
3593c5f
+
3593c5f
+  It is imperative that the returned pointer is used. Pointers which are
3593c5f
+  generated separately are subject to a number of potential CPU and compiler
3593c5f
+  optimizations, and may still be used speculatively. For example, this means
3593c5f
+  that the following sequence is unsafe:
3593c5f
+
3593c5f
+	struct foo array[SIZE];
3593c5f
+	int a, b;
3593c5f
+
3593c5f
+	void do_thing(int idx)
3593c5f
+	{
3593c5f
+		if (nospec_ptr(array + idx, array, array + SIZE) != NULL) {
3593c5f
+			// unsafe as wrong pointer is used
3593c5f
+			a = array[idx].field_a;
3593c5f
+			b = array[idx].field_b;
3593c5f
+		}
3593c5f
+	}
3593c5f
+
3593c5f
+  Similarly, it is unsafe to compare the returned pointer with other pointers,
3593c5f
+  as this may permit the compiler to substitute one pointer with another,
3593c5f
+  permitting speculation. For example, the following sequence is unsafe:
3593c5f
+
3593c5f
+	struct foo array[SIZE];
3593c5f
+	int a, b;
3593c5f
+
3593c5f
+	void do_thing(int idx)
3593c5f
+	{
3593c5f
+		struct foo *elem = nospec_ptr(array + idx, array, array + size);
3593c5f
+
3593c5f
+		// unsafe due to pointer substitution
3593c5f
+		if (elem == &array[idx]) {
3593c5f
+			a = elem->field_a;
3593c5f
+			b = elem->field_b;
3593c5f
+		}
3593c5f
+	}
3593c5f
+
3593c5f
+* nospec_array_ptr(arr, idx, sz)
3593c5f
+
3593c5f
+  Returns a sanitized pointer to arr[idx] only if idx falls in the [0, sz)
3593c5f
+  interval. When idx < 0 or idx > sz, NULL is returned. Prevents an
3593c5f
+  out-of-bounds pointer being propagated to code which is speculatively
3593c5f
+  executed.
3593c5f
+
3593c5f
+  This is a convenience function which wraps nospec_ptr(), and has the same
3593c5f
+  caveats w.r.t. the use of the returned pointer.
3593c5f
+
3593c5f
+  For example, this may be used as follows:
3593c5f
+
3593c5f
+  int load_array(int *array, unsigned int idx)
3593c5f
+  {
3593c5f
+	int *elem;
3593c5f
+
3593c5f
+	if ((elem = nospec_array_ptr(array, idx, MAX_ARRAY_ELEMS)))
3593c5f
+		return *elem;
3593c5f
+	else
3593c5f
+		return 0;
3593c5f
+  }
3593c5f
+
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From 2b98026ffeeb0b4a06c80fe39bfebd5cef4a8fa6 Mon Sep 17 00:00:00 2001
3593c5f
From: Mark Rutland <mark.rutland@arm.com>
3593c5f
Date: Thu, 7 Dec 2017 17:15:01 +0000
3593c5f
Subject: [PATCH 03/19] arm64: implement nospec_ptr()
3593c5f
3593c5f
This patch implements nospec_ptr() for arm64, following the recommended
3593c5f
architectural sequence.
3593c5f
3593c5f
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
3593c5f
Signed-off-by: Will Deacon <will.deacon@arm.com>
3593c5f
Cc: Dan Williams <dan.j.williams@intel.com>
3593c5f
Cc: Peter Zijlstra <peterz@infradead.org>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 arch/arm64/include/asm/barrier.h | 55 ++++++++++++++++++++++++++++++++++++++++
3593c5f
 1 file changed, 55 insertions(+)
3593c5f
3593c5f
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
3593c5f
index 77651c49ef44..b4819f6a0e5c 100644
3593c5f
--- a/arch/arm64/include/asm/barrier.h
3593c5f
+++ b/arch/arm64/include/asm/barrier.h
3593c5f
@@ -40,6 +40,61 @@
3593c5f
 #define dma_rmb()	dmb(oshld)
3593c5f
 #define dma_wmb()	dmb(oshst)
3593c5f
3593c5f
+#define __load_no_speculate_n(ptr, lo, hi, failval, cmpptr, w, sz)	\
3593c5f
+({									\
3593c5f
+	typeof(*ptr)	__nln_val;					\
3593c5f
+	typeof(*ptr)	__failval = 					\
3593c5f
+		(typeof(*ptr))(unsigned long)(failval);			\
3593c5f
+									\
3593c5f
+	asm volatile (							\
3593c5f
+	"	cmp	%[c], %[l]\n"					\
3593c5f
+	"	ccmp	%[c], %[h], 2, cs\n"				\
3593c5f
+	"	b.cs	1f\n"						\
3593c5f
+	"	ldr" #sz " %" #w "[v], %[p]\n"				\
3593c5f
+	"1:	csel	%" #w "[v], %" #w "[v], %" #w "[f], cc\n"	\
3593c5f
+	"	hint	#0x14 // CSDB\n"				\
3593c5f
+	: [v] "=&r" (__nln_val)						\
3593c5f
+	: [p] "m" (*(ptr)), [l] "r" (lo), [h] "r" (hi),			\
3593c5f
+	  [f] "rZ" (__failval), [c] "r" (cmpptr)			\
3593c5f
+	: "cc");							\
3593c5f
+									\
3593c5f
+	__nln_val;							\
3593c5f
+})
3593c5f
+
3593c5f
+#define __load_no_speculate(ptr, lo, hi, failval, cmpptr)		\
3593c5f
+({									\
3593c5f
+	typeof(*(ptr)) __nl_val;					\
3593c5f
+									\
3593c5f
+	switch (sizeof(__nl_val)) {					\
3593c5f
+	case 1:								\
3593c5f
+		__nl_val = __load_no_speculate_n(ptr, lo, hi, failval,	\
3593c5f
+						 cmpptr, w, b);		\
3593c5f
+		break;							\
3593c5f
+	case 2:								\
3593c5f
+		__nl_val = __load_no_speculate_n(ptr, lo, hi, failval,	\
3593c5f
+						 cmpptr, w, h);		\
3593c5f
+		break;							\
3593c5f
+	case 4:								\
3593c5f
+		__nl_val = __load_no_speculate_n(ptr, lo, hi, failval,	\
3593c5f
+						 cmpptr, w, );		\
3593c5f
+		break;							\
3593c5f
+	case 8:								\
3593c5f
+		__nl_val = __load_no_speculate_n(ptr, lo, hi, failval,	\
3593c5f
+						 cmpptr, x, );		\
3593c5f
+		break;							\
3593c5f
+	default:							\
3593c5f
+		BUILD_BUG();						\
3593c5f
+	}								\
3593c5f
+									\
3593c5f
+	__nl_val;							\
3593c5f
+})
3593c5f
+
3593c5f
+#define nospec_ptr(ptr, lo, hi)						\
3593c5f
+({									\
3593c5f
+	typeof(ptr) __np_ptr = (ptr);					\
3593c5f
+	__load_no_speculate(&__np_ptr, lo, hi, 0, __np_ptr);		\
3593c5f
+})
3593c5f
+
3593c5f
 #define __smp_mb()	dmb(ish)
3593c5f
 #define __smp_rmb()	dmb(ishld)
3593c5f
 #define __smp_wmb()	dmb(ishst)
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From cedaed8d38108dc6b68c1418d9b942f64b2be488 Mon Sep 17 00:00:00 2001
3593c5f
From: Mark Rutland <mark.rutland@arm.com>
3593c5f
Date: Fri, 5 Jan 2018 16:44:36 +0000
3593c5f
Subject: [PATCH 04/19] arm: implement nospec_ptr()
3593c5f
3593c5f
This patch implements nospec_ptr() for arm, following the recommended
3593c5f
architectural sequences for the arm and thumb instruction sets.
3593c5f
3593c5f
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 arch/arm/include/asm/barrier.h | 75 ++++++++++++++++++++++++++++++++++++++++++
3593c5f
 1 file changed, 75 insertions(+)
3593c5f
3593c5f
diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h
3593c5f
index 40f5c410fd8c..6384c90e4b72 100644
3593c5f
--- a/arch/arm/include/asm/barrier.h
3593c5f
+++ b/arch/arm/include/asm/barrier.h
3593c5f
@@ -37,6 +37,81 @@
3593c5f
 #define dmb(x) __asm__ __volatile__ ("" : : : "memory")
3593c5f
 #endif
3593c5f
3593c5f
+#ifdef CONFIG_THUMB2_KERNEL
3593c5f
+#define __load_no_speculate_n(ptr, lo, hi, failval, cmpptr, sz)	\
3593c5f
+({								\
3593c5f
+	typeof(*ptr) __nln_val;					\
3593c5f
+	typeof(*ptr) __failval =				\
e894e5d
+		(typeof(*ptr))(unsigned long)(failval);		\
3593c5f
+								\
3593c5f
+	asm volatile (						\
3593c5f
+	"	cmp	%[c], %[l]\n"				\
3593c5f
+	"	it	hs\n"					\
3593c5f
+	"	cmphs	%[h], %[c]\n"				\
3593c5f
+	"	blo	1f\n"					\
3593c5f
+	"	ld" #sz " %[v], %[p]\n"				\
3593c5f
+	"1:	it	lo\n"					\
3593c5f
+	"	movlo	%[v], %[f]\n"				\
3593c5f
+	"	.inst 0xf3af8014 @ CSDB\n"			\
3593c5f
+	: [v] "=&r" (__nln_val)					\
3593c5f
+	: [p] "m" (*(ptr)), [l] "r" (lo), [h] "r" (hi),		\
3593c5f
+	  [f] "r" (__failval), [c] "r" (cmpptr)			\
3593c5f
+	: "cc");						\
3593c5f
+								\
3593c5f
+	__nln_val;						\
3593c5f
+})
3593c5f
+#else
3593c5f
+#define __load_no_speculate_n(ptr, lo, hi, failval, cmpptr, sz)	\
3593c5f
+({								\
3593c5f
+	typeof(*ptr) __nln_val;					\
3593c5f
+	typeof(*ptr) __failval =				\
6a7b2a7
+		(typeof(*ptr))(unsigned long)(failval);		\
3593c5f
+								\
3593c5f
+	asm volatile (						\
3593c5f
+	"	cmp	%[c], %[l]\n"				\
3593c5f
+	"	cmphs	%[h], %[c]\n"				\
3593c5f
+	"	ldr" #sz "hi %[v], %[p]\n"			\
3593c5f
+	"	movls	%[v], %[f]\n"				\
3593c5f
+	"	.inst 0xe320f014 @ CSDB\n"			\
3593c5f
+	: [v] "=&r" (__nln_val)					\
3593c5f
+	: [p] "m" (*(ptr)), [l] "r" (lo), [h] "r" (hi),		\
3593c5f
+	  [f] "r" (__failval), [c] "r" (cmpptr)			\
3593c5f
+	: "cc");						\
3593c5f
+								\
3593c5f
+	__nln_val;						\
3593c5f
+})
3593c5f
+#endif
3593c5f
+
3593c5f
+#define __load_no_speculate(ptr, lo, hi, failval, cmpptr)		\
3593c5f
+({									\
3593c5f
+	typeof(*(ptr)) __nl_val;					\
3593c5f
+									\
3593c5f
+	switch (sizeof(__nl_val)) {					\
3593c5f
+	case 1:								\
3593c5f
+		__nl_val = __load_no_speculate_n(ptr, lo, hi, failval,	\
3593c5f
+						 cmpptr, b);		\
3593c5f
+		break;							\
3593c5f
+	case 2:								\
3593c5f
+		__nl_val = __load_no_speculate_n(ptr, lo, hi, failval,	\
3593c5f
+						 cmpptr, h);		\
3593c5f
+		break;							\
3593c5f
+	case 4:								\
3593c5f
+		__nl_val = __load_no_speculate_n(ptr, lo, hi, failval,	\
3593c5f
+						 cmpptr, );		\
3593c5f
+		break;							\
3593c5f
+	default:							\
3593c5f
+		BUILD_BUG();						\
3593c5f
+	}								\
3593c5f
+									\
3593c5f
+	__nl_val;							\
3593c5f
+})
3593c5f
+
3593c5f
+#define nospec_ptr(ptr, lo, hi)						\
3593c5f
+({									\
3593c5f
+	typeof(ptr) __np_ptr = (ptr);					\
3593c5f
+	__load_no_speculate(&__np_ptr, lo, hi, 0, __np_ptr);		\
3593c5f
+})
3593c5f
+
3593c5f
 #ifdef CONFIG_ARM_HEAVY_MB
3593c5f
 extern void (*soc_mb)(void);
3593c5f
 extern void arm_heavy_mb(void);
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From d14a4150a2f74a068247cf3846405904e21a8d2c Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 14:51:58 -0800
3593c5f
Subject: [PATCH 05/19] x86: implement nospec_barrier()
3593c5f
3593c5f
The new speculative execution barrier, nospec_barrier(), ensures
3593c5f
that any userspace controllable speculation doesn't cross the boundary.
3593c5f
3593c5f
Any user observable speculative activity on this CPU thread before this
3593c5f
point either completes, reaches a state it can no longer cause an
3593c5f
observable activity, or is aborted before instructions after the barrier
3593c5f
execute.
3593c5f
3593c5f
In the x86 case nospec_barrier() resolves to an lfence if
3593c5f
X86_FEATURE_LFENCE_RDTSC is present. Other architectures can define
3593c5f
their variants.
3593c5f
3593c5f
Note the expectation is that this barrier is never used directly, at
3593c5f
least outside of architecture specific code. It is implied by the
3593c5f
nospec_{array_ptr,ptr} macros.
3593c5f
3593c5f
x86, for now, depends on the barrier for protection while other
3593c5f
architectures place their speculation prevention in
3593c5f
nospec_{ptr,array_ptr} when a barrier instruction is not available or
3593c5f
too heavy-weight. In the x86 case lfence is not a fully serializing
3593c5f
instruction so it is not as expensive as other barriers.
3593c5f
3593c5f
Suggested-by: Peter Zijlstra <peterz@infradead.org>
3593c5f
Suggested-by: Arjan van de Ven <arjan@linux.intel.com>
3593c5f
Suggested-by: Alan Cox <alan.cox@intel.com>
3593c5f
Cc: Mark Rutland <mark.rutland@arm.com>
3593c5f
Cc: Greg KH <gregkh@linuxfoundation.org>
3593c5f
Cc: Thomas Gleixner <tglx@linutronix.de>
3593c5f
Cc: Alan Cox <alan@linux.intel.com>
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 arch/x86/include/asm/barrier.h | 6 ++++++
3593c5f
 1 file changed, 6 insertions(+)
3593c5f
3593c5f
diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
3593c5f
index 7fb336210e1b..1148cd9f5ae7 100644
3593c5f
--- a/arch/x86/include/asm/barrier.h
3593c5f
+++ b/arch/x86/include/asm/barrier.h
3593c5f
@@ -24,6 +24,12 @@
3593c5f
 #define wmb()	asm volatile("sfence" ::: "memory")
3593c5f
 #endif
3593c5f
3593c5f
+/*
3593c5f
+ * CPUs without LFENCE don't really speculate much. Possibly fall back to IRET-to-self.
3593c5f
+ */
3593c5f
+#define __nospec_barrier() alternative("", "lfence", X86_FEATURE_LFENCE_RDTSC)
3593c5f
+#define nospec_barrier __nospec_barrier
3593c5f
+
3593c5f
 #ifdef CONFIG_X86_PPRO_FENCE
3593c5f
 #define dma_rmb()	rmb()
3593c5f
 #else
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From d077f11b7fcb697af0c9419cc2273d179e6f51ad Mon Sep 17 00:00:00 2001
3593c5f
From: Andi Kleen <ak@linux.intel.com>
3593c5f
Date: Thu, 4 Jan 2018 13:36:20 -0800
3593c5f
Subject: [PATCH 06/19] x86, barrier: stop speculation for failed access_ok
3593c5f
3593c5f
When access_ok fails we should always stop speculating.
3593c5f
Add the required barriers to the x86 access_ok macro.
3593c5f
3593c5f
Cc: Thomas Gleixner <tglx@linutronix.de>
3593c5f
Cc: Ingo Molnar <mingo@redhat.com>
3593c5f
Cc: "H. Peter Anvin" <hpa@zytor.com>
3593c5f
Cc: Arnd Bergmann <arnd@arndb.de>
3593c5f
Cc: x86@kernel.org
3593c5f
Signed-off-by: Andi Kleen <ak@linux.intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 arch/x86/include/asm/uaccess.h | 17 +++++++++++++----
3593c5f
 include/asm-generic/barrier.h  |  6 +++---
3593c5f
 2 files changed, 16 insertions(+), 7 deletions(-)
3593c5f
3593c5f
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
3593c5f
index 574dff4d2913..9b6f20cfaeb9 100644
3593c5f
--- a/arch/x86/include/asm/uaccess.h
3593c5f
+++ b/arch/x86/include/asm/uaccess.h
3593c5f
@@ -43,6 +43,8 @@ static inline void set_fs(mm_segment_t fs)
3593c5f
 /*
3593c5f
  * Test whether a block of memory is a valid user space address.
3593c5f
  * Returns 0 if the range is valid, nonzero otherwise.
3593c5f
+ *
3593c5f
+ * We also disable speculation when a check fails.
3593c5f
  */
3593c5f
 static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, unsigned long limit)
3593c5f
 {
3593c5f
@@ -53,14 +55,19 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
3593c5f
 	 * important to subtract the size from the
3593c5f
 	 * limit, not add it to the address).
3593c5f
 	 */
3593c5f
-	if (__builtin_constant_p(size))
3593c5f
-		return unlikely(addr > limit - size);
3593c5f
+	if (__builtin_constant_p(size)) {
3593c5f
+		if (unlikely(addr > limit - size))
3593c5f
+			return true;
3593c5f
+		nospec_barrier();
3593c5f
+		return false;
3593c5f
+	}
3593c5f
3593c5f
 	/* Arbitrary sizes? Be careful about overflow */
3593c5f
 	addr += size;
3593c5f
-	if (unlikely(addr < size))
3593c5f
+	if (unlikely(addr < size || addr > limit))
3593c5f
 		return true;
3593c5f
-	return unlikely(addr > limit);
3593c5f
+	nospec_barrier();
3593c5f
+	return false;
3593c5f
 }
3593c5f
3593c5f
 #define __range_not_ok(addr, size, limit)				\
3593c5f
@@ -94,6 +101,8 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
3593c5f
  * Note that, depending on architecture, this function probably just
3593c5f
  * checks that the pointer is in the user space range - after calling
3593c5f
  * this function, memory access functions may still return -EFAULT.
3593c5f
+ *
3593c5f
+ * Stops speculation automatically
3593c5f
  */
3593c5f
 #define access_ok(type, addr, size)					\
3593c5f
 ({									\
3593c5f
diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
3593c5f
index 91c3071f49e5..a11765eba860 100644
3593c5f
--- a/include/asm-generic/barrier.h
3593c5f
+++ b/include/asm-generic/barrier.h
3593c5f
@@ -59,7 +59,9 @@
3593c5f
  *
3593c5f
  * Architectures with a suitable memory barrier should provide an
3593c5f
  * implementation. This is non-portable, and generic code should use
3593c5f
- * nospec_ptr().
3593c5f
+ * nospec_{array_ptr,ptr}. Arch-specific code should define and use
3593c5f
+ * nospec_barrier() for usages where nospec_{array_ptr,ptr} is
3593c5f
+ * unsuitable.
3593c5f
  */
3593c5f
 #ifndef __nospec_barrier
3593c5f
 #define __nospec_barrier()		do { } while (0)
3593c5f
@@ -120,8 +122,6 @@
3593c5f
 	nospec_ptr(__arr + __idx, __arr, __arr + __sz);			\
3593c5f
 })
3593c5f
3593c5f
-#undef __nospec_barrier
3593c5f
-
3593c5f
 #ifndef __smp_mb
3593c5f
 #define __smp_mb()	mb()
3593c5f
 #endif
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From bb10d660be01a93f19d258260dd25444e14e5889 Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:53:55 -0800
3593c5f
Subject: [PATCH 07/19] [media] uvcvideo: prevent bounds-check bypass via
3593c5f
 speculative execution
3593c5f
3593c5f
Static analysis reports that 'index' may be a user controlled value that
3593c5f
is used as a data dependency to read 'pin' from the
3593c5f
'selector->baSourceID' array. In order to avoid potential leaks of
3593c5f
kernel memory values, block speculative execution of the instruction
3593c5f
stream that could issue reads based on an invalid value of 'pin'.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3593c5f
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
3593c5f
Cc: linux-media@vger.kernel.org
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 drivers/media/usb/uvc/uvc_v4l2.c | 7 +++++--
3593c5f
 1 file changed, 5 insertions(+), 2 deletions(-)
3593c5f
3593c5f
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
3593c5f
index 3e7e283a44a8..7442626dc20e 100644
3593c5f
--- a/drivers/media/usb/uvc/uvc_v4l2.c
3593c5f
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
3593c5f
@@ -22,6 +22,7 @@
3593c5f
 #include <linux/mm.h>
3593c5f
 #include <linux/wait.h>
3593c5f
 #include <linux/atomic.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
3593c5f
 #include <media/v4l2-common.h>
3593c5f
 #include <media/v4l2-ctrls.h>
3593c5f
@@ -810,6 +811,7 @@ static int uvc_ioctl_enum_input(struct file *file, void *fh,
3593c5f
 	struct uvc_entity *iterm = NULL;
3593c5f
 	u32 index = input->index;
3593c5f
 	int pin = 0;
3593c5f
+	__u8 *elem;
3593c5f
3593c5f
 	if (selector == NULL ||
3593c5f
 	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
3593c5f
@@ -820,8 +822,9 @@ static int uvc_ioctl_enum_input(struct file *file, void *fh,
3593c5f
 				break;
3593c5f
 		}
3593c5f
 		pin = iterm->id;
3593c5f
-	} else if (index < selector->bNrInPins) {
3593c5f
-		pin = selector->baSourceID[index];
3593c5f
+	} else if ((elem = nospec_array_ptr(selector->baSourceID, index,
3593c5f
+					selector->bNrInPins))) {
3593c5f
+		pin = *elem;
3593c5f
 		list_for_each_entry(iterm, &chain->entities, chain) {
3593c5f
 			if (!UVC_ENTITY_IS_ITERM(iterm))
3593c5f
 				continue;
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From 8a4e4e1e674b9aaf0d2ca95c3fa5117ab5aa2987 Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:53:56 -0800
3593c5f
Subject: [PATCH 08/19] carl9170: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'queue' may be a user controlled value that
3593c5f
is used as a data dependency to read from the 'ar9170_qmap' array. In
3593c5f
order to avoid potential leaks of kernel memory values, block
3593c5f
speculative execution of the instruction stream that could issue reads
3593c5f
based on an invalid result of 'ar9170_qmap[queue]'. In this case the
3593c5f
value of 'ar9170_qmap[queue]' is immediately reused as an index to the
3593c5f
'ar->edcf' array.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: Christian Lamparter <chunkeey@googlemail.com>
3593c5f
Cc: Kalle Valo <kvalo@codeaurora.org>
3593c5f
Cc: linux-wireless@vger.kernel.org
3593c5f
Cc: netdev@vger.kernel.org
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 drivers/net/wireless/ath/carl9170/main.c | 6 ++++--
3593c5f
 1 file changed, 4 insertions(+), 2 deletions(-)
3593c5f
3593c5f
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
3593c5f
index 988c8857d78c..0ff34cbe2b62 100644
3593c5f
--- a/drivers/net/wireless/ath/carl9170/main.c
3593c5f
+++ b/drivers/net/wireless/ath/carl9170/main.c
3593c5f
@@ -41,6 +41,7 @@
3593c5f
 #include <linux/module.h>
3593c5f
 #include <linux/etherdevice.h>
3593c5f
 #include <linux/random.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
 #include <net/mac80211.h>
3593c5f
 #include <net/cfg80211.h>
3593c5f
 #include "hw.h"
3593c5f
@@ -1384,11 +1385,12 @@ static int carl9170_op_conf_tx(struct ieee80211_hw *hw,
3593c5f
 			       const struct ieee80211_tx_queue_params *param)
3593c5f
 {
3593c5f
 	struct ar9170 *ar = hw->priv;
3593c5f
+	const u8 *elem;
3593c5f
 	int ret;
3593c5f
3593c5f
 	mutex_lock(&ar->mutex);
3593c5f
-	if (queue < ar->hw->queues) {
3593c5f
-		memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param));
3593c5f
+	if ((elem = nospec_array_ptr(ar9170_qmap, queue, ar->hw->queues))) {
3593c5f
+		memcpy(&ar->edcf[*elem], param, sizeof(*param));
3593c5f
 		ret = carl9170_set_qos(ar);
3593c5f
 	} else {
3593c5f
 		ret = -EINVAL;
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From b2134ba6dc16b4e6a232e34179c3489c3e51ba89 Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:53:57 -0800
3593c5f
Subject: [PATCH 09/19] p54: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'queue' may be a user controlled value that
3593c5f
is used as a data dependency to read from the 'priv->qos_params' array.
3593c5f
In order to avoid potential leaks of kernel memory values, block
3593c5f
speculative execution of the instruction stream that could issue reads
3593c5f
based on an invalid result of 'priv->qos_params[queue]'.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: Christian Lamparter <chunkeey@googlemail.com>
3593c5f
Cc: Kalle Valo <kvalo@codeaurora.org>
3593c5f
Cc: linux-wireless@vger.kernel.org
3593c5f
Cc: netdev@vger.kernel.org
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 drivers/net/wireless/intersil/p54/main.c | 8 +++++---
3593c5f
 1 file changed, 5 insertions(+), 3 deletions(-)
3593c5f
3593c5f
diff --git a/drivers/net/wireless/intersil/p54/main.c b/drivers/net/wireless/intersil/p54/main.c
3593c5f
index ab6d39e12069..85c9cbee35fc 100644
3593c5f
--- a/drivers/net/wireless/intersil/p54/main.c
3593c5f
+++ b/drivers/net/wireless/intersil/p54/main.c
3593c5f
@@ -20,6 +20,7 @@
3593c5f
 #include <linux/firmware.h>
3593c5f
 #include <linux/etherdevice.h>
3593c5f
 #include <linux/module.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
3593c5f
 #include <net/mac80211.h>
3593c5f
3593c5f
@@ -411,12 +412,13 @@ static int p54_conf_tx(struct ieee80211_hw *dev,
3593c5f
 		       const struct ieee80211_tx_queue_params *params)
3593c5f
 {
3593c5f
 	struct p54_common *priv = dev->priv;
3593c5f
+	struct p54_edcf_queue_param *p54_q;
3593c5f
 	int ret;
3593c5f
3593c5f
 	mutex_lock(&priv->conf_mutex);
3593c5f
-	if (queue < dev->queues) {
3593c5f
-		P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
3593c5f
-			params->cw_min, params->cw_max, params->txop);
3593c5f
+	if ((p54_q = nospec_array_ptr(priv->qos_params, queue, dev->queues))) {
3593c5f
+		P54_SET_QUEUE(p54_q[0], params->aifs, params->cw_min,
3593c5f
+				params->cw_max, params->txop);
3593c5f
 		ret = p54_set_edcf(priv);
3593c5f
 	} else
3593c5f
 		ret = -EINVAL;
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From addb69e8d90a79887aa369398e73b9b64fb9e910 Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:53:58 -0800
3593c5f
Subject: [PATCH 10/19] qla2xxx: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'handle' may be a user controlled value
3593c5f
that is used as a data dependency to read 'sp' from the
3593c5f
'req->outstanding_cmds' array.  In order to avoid potential leaks of
3593c5f
kernel memory values, block speculative execution of the instruction
3593c5f
stream that could issue reads based on an invalid value of 'sp'. In this
3593c5f
case 'sp' is directly dereferenced later in the function.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: qla2xxx-upstream@qlogic.com
3593c5f
Cc: "James E.J. Bottomley" <jejb@linux.vnet.ibm.com>
3593c5f
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
3593c5f
Cc: linux-scsi@vger.kernel.org
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 drivers/scsi/qla2xxx/qla_mr.c | 15 +++++++++------
3593c5f
 1 file changed, 9 insertions(+), 6 deletions(-)
3593c5f
3593c5f
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
3593c5f
index d5da3981cefe..128b41de3784 100644
3593c5f
--- a/drivers/scsi/qla2xxx/qla_mr.c
3593c5f
+++ b/drivers/scsi/qla2xxx/qla_mr.c
3593c5f
@@ -9,6 +9,7 @@
3593c5f
 #include <linux/ktime.h>
3593c5f
 #include <linux/pci.h>
3593c5f
 #include <linux/ratelimit.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
 #include <linux/vmalloc.h>
3593c5f
 #include <linux/bsg-lib.h>
3593c5f
 #include <scsi/scsi_tcq.h>
3593c5f
@@ -2275,7 +2276,7 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req,
3593c5f
 static void
3593c5f
 qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
3593c5f
 {
3593c5f
-	srb_t		*sp;
3593c5f
+	srb_t		*sp, **elem;
3593c5f
 	fc_port_t	*fcport;
3593c5f
 	struct scsi_cmnd *cp;
3593c5f
 	struct sts_entry_fx00 *sts;
3593c5f
@@ -2304,8 +2305,9 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
3593c5f
 	req = ha->req_q_map[que];
3593c5f
3593c5f
 	/* Validate handle. */
3593c5f
-	if (handle < req->num_outstanding_cmds)
3593c5f
-		sp = req->outstanding_cmds[handle];
3593c5f
+	if ((elem = nospec_array_ptr(req->outstanding_cmds, handle,
3593c5f
+					req->num_outstanding_cmds)))
3593c5f
+		sp = *elem;
3593c5f
 	else
3593c5f
 		sp = NULL;
3593c5f
3593c5f
@@ -2626,7 +2628,7 @@ static void
3593c5f
 qlafx00_multistatus_entry(struct scsi_qla_host *vha,
3593c5f
 	struct rsp_que *rsp, void *pkt)
3593c5f
 {
3593c5f
-	srb_t		*sp;
3593c5f
+	srb_t		*sp, **elem;
3593c5f
 	struct multi_sts_entry_fx00 *stsmfx;
3593c5f
 	struct qla_hw_data *ha = vha->hw;
3593c5f
 	uint32_t handle, hindex, handle_count, i;
3593c5f
@@ -2655,8 +2657,9 @@ qlafx00_multistatus_entry(struct scsi_qla_host *vha,
3593c5f
 		req = ha->req_q_map[que];
3593c5f
3593c5f
 		/* Validate handle. */
3593c5f
-		if (handle < req->num_outstanding_cmds)
3593c5f
-			sp = req->outstanding_cmds[handle];
3593c5f
+		if ((elem = nospec_array_ptr(req->outstanding_cmds, handle,
3593c5f
+						req->num_outstanding_cmds)))
3593c5f
+			sp = *elem;
3593c5f
 		else
3593c5f
 			sp = NULL;
3593c5f
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From 18e5e10139f6a04e00f6522c4b0091f167eb6c1d Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:54:00 -0800
3593c5f
Subject: [PATCH 11/19] cw1200: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'queue' may be a user controlled value that
3593c5f
is used as a data dependency to read 'txq_params' from the
3593c5f
'priv->tx_queue_params.params' array.  In order to avoid potential leaks
3593c5f
of kernel memory values, block speculative execution of the instruction
3593c5f
stream that could issue reads based on an invalid value of 'txq_params'.
3593c5f
In this case 'txq_params' is referenced later in the function.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: Solomon Peachy <pizza@shaftnet.org>
3593c5f
Cc: Kalle Valo <kvalo@codeaurora.org>
3593c5f
Cc: linux-wireless@vger.kernel.org
3593c5f
Cc: netdev@vger.kernel.org
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 drivers/net/wireless/st/cw1200/sta.c | 10 ++++++----
3593c5f
 drivers/net/wireless/st/cw1200/wsm.h |  4 +---
3593c5f
 2 files changed, 7 insertions(+), 7 deletions(-)
3593c5f
3593c5f
diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c
3593c5f
index 38678e9a0562..886942617f14 100644
3593c5f
--- a/drivers/net/wireless/st/cw1200/sta.c
3593c5f
+++ b/drivers/net/wireless/st/cw1200/sta.c
3593c5f
@@ -14,6 +14,7 @@
3593c5f
 #include <linux/firmware.h>
3593c5f
 #include <linux/module.h>
3593c5f
 #include <linux/etherdevice.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
3593c5f
 #include "cw1200.h"
3593c5f
 #include "sta.h"
3593c5f
@@ -612,18 +613,19 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
3593c5f
 		   u16 queue, const struct ieee80211_tx_queue_params *params)
3593c5f
 {
3593c5f
 	struct cw1200_common *priv = dev->priv;
3593c5f
+	struct wsm_set_tx_queue_params *txq_params;
3593c5f
 	int ret = 0;
3593c5f
 	/* To prevent re-applying PM request OID again and again*/
3593c5f
 	bool old_uapsd_flags;
3593c5f
3593c5f
 	mutex_lock(&priv->conf_mutex);
3593c5f
3593c5f
-	if (queue < dev->queues) {
3593c5f
+	if ((txq_params = nospec_array_ptr(priv->tx_queue_params.params,
3593c5f
+					queue, dev->queues))) {
3593c5f
 		old_uapsd_flags = le16_to_cpu(priv->uapsd_info.uapsd_flags);
3593c5f
3593c5f
-		WSM_TX_QUEUE_SET(&priv->tx_queue_params, queue, 0, 0, 0);
3593c5f
-		ret = wsm_set_tx_queue_params(priv,
3593c5f
-					      &priv->tx_queue_params.params[queue], queue);
3593c5f
+		WSM_TX_QUEUE_SET(txq_params, 0, 0, 0);
3593c5f
+		ret = wsm_set_tx_queue_params(priv, txq_params, queue);
3593c5f
 		if (ret) {
3593c5f
 			ret = -EINVAL;
3593c5f
 			goto out;
3593c5f
diff --git a/drivers/net/wireless/st/cw1200/wsm.h b/drivers/net/wireless/st/cw1200/wsm.h
3593c5f
index 48086e849515..8c8d9191e233 100644
3593c5f
--- a/drivers/net/wireless/st/cw1200/wsm.h
3593c5f
+++ b/drivers/net/wireless/st/cw1200/wsm.h
3593c5f
@@ -1099,10 +1099,8 @@ struct wsm_tx_queue_params {
3593c5f
 };
3593c5f
3593c5f
3593c5f
-#define WSM_TX_QUEUE_SET(queue_params, queue, ack_policy, allowed_time,\
3593c5f
-		max_life_time)	\
3593c5f
+#define WSM_TX_QUEUE_SET(p, ack_policy, allowed_time, max_life_time)	\
3593c5f
 do {							\
3593c5f
-	struct wsm_set_tx_queue_params *p = &(queue_params)->params[queue]; \
3593c5f
 	p->ackPolicy = (ack_policy);				\
3593c5f
 	p->allowedMediumTime = (allowed_time);				\
3593c5f
 	p->maxTransmitLifetime = (max_life_time);			\
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From 0096694093529628e2a855812a5111358d1e952d Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:54:01 -0800
3593c5f
Subject: [PATCH 12/19] Thermal/int340x: prevent bounds-check bypass via
3593c5f
 speculative execution
3593c5f
3593c5f
Static analysis reports that 'trip' may be a user controlled value that
3593c5f
is used as a data dependency to read '*temp' from the 'd->aux_trips'
3593c5f
array.  In order to avoid potential leaks of kernel memory values, block
3593c5f
speculative execution of the instruction stream that could issue reads
3593c5f
based on an invalid value of '*temp'.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
3593c5f
Cc: Zhang Rui <rui.zhang@intel.com>
3593c5f
Cc: Eduardo Valentin <edubezval@gmail.com>
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 drivers/thermal/int340x_thermal/int340x_thermal_zone.c | 14 ++++++++------
3593c5f
 1 file changed, 8 insertions(+), 6 deletions(-)
3593c5f
3593c5f
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
3593c5f
index 145a5c53ff5c..442a1d9bf7ad 100644
3593c5f
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
3593c5f
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
3593c5f
@@ -17,6 +17,7 @@
3593c5f
 #include <linux/init.h>
3593c5f
 #include <linux/acpi.h>
3593c5f
 #include <linux/thermal.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
 #include "int340x_thermal_zone.h"
3593c5f
3593c5f
 static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
3593c5f
@@ -52,20 +53,21 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
3593c5f
 					 int trip, int *temp)
3593c5f
 {
3593c5f
 	struct int34x_thermal_zone *d = zone->devdata;
3593c5f
+	unsigned long *elem;
3593c5f
 	int i;
3593c5f
3593c5f
 	if (d->override_ops && d->override_ops->get_trip_temp)
3593c5f
 		return d->override_ops->get_trip_temp(zone, trip, temp);
3593c5f
3593c5f
-	if (trip < d->aux_trip_nr)
3593c5f
-		*temp = d->aux_trips[trip];
3593c5f
-	else if (trip == d->crt_trip_id)
3593c5f
+	if ((elem = nospec_array_ptr(d->aux_trips, trip, d->aux_trip_nr))) {
3593c5f
+		*temp = *elem;
3593c5f
+	} else if (trip == d->crt_trip_id) {
3593c5f
 		*temp = d->crt_temp;
3593c5f
-	else if (trip == d->psv_trip_id)
3593c5f
+	} else if (trip == d->psv_trip_id) {
3593c5f
 		*temp = d->psv_temp;
3593c5f
-	else if (trip == d->hot_trip_id)
3593c5f
+	} else if (trip == d->hot_trip_id) {
3593c5f
 		*temp = d->hot_temp;
3593c5f
-	else {
3593c5f
+	} else {
3593c5f
 		for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
3593c5f
 			if (d->act_trips[i].valid &&
3593c5f
 			    d->act_trips[i].id == trip) {
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From 2a5a165ff05df37c3f4d02ab70ddee1e9329401c Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:54:03 -0800
3593c5f
Subject: [PATCH 13/19] ipv6: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'offset' may be a user controlled value
3593c5f
that is used as a data dependency reading from a raw6_frag_vec buffer.
3593c5f
In order to avoid potential leaks of kernel memory values, block
3593c5f
speculative execution of the instruction stream that could issue further
3593c5f
reads based on an invalid '*(rfv->c + offset)' value.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: "David S. Miller" <davem@davemloft.net>
3593c5f
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
3593c5f
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
3593c5f
Cc: netdev@vger.kernel.org
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 net/ipv6/raw.c | 9 +++++----
3593c5f
 1 file changed, 5 insertions(+), 4 deletions(-)
3593c5f
3593c5f
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
3593c5f
index 761a473a07c5..384e3d59d148 100644
3593c5f
--- a/net/ipv6/raw.c
3593c5f
+++ b/net/ipv6/raw.c
3593c5f
@@ -33,6 +33,7 @@
3593c5f
 #include <linux/skbuff.h>
3593c5f
 #include <linux/compat.h>
3593c5f
 #include <linux/uaccess.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
 #include <asm/ioctls.h>
3593c5f
3593c5f
 #include <net/net_namespace.h>
3593c5f
@@ -725,17 +726,17 @@ static int raw6_getfrag(void *from, char *to, int offset, int len, int odd,
3593c5f
 		       struct sk_buff *skb)
3593c5f
 {
3593c5f
 	struct raw6_frag_vec *rfv = from;
3593c5f
+	char *rfv_buf;
3593c5f
3593c5f
-	if (offset < rfv->hlen) {
3593c5f
+	if ((rfv_buf = nospec_array_ptr(rfv->c, offset, rfv->hlen))) {
3593c5f
 		int copy = min(rfv->hlen - offset, len);
3593c5f
3593c5f
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
3593c5f
-			memcpy(to, rfv->c + offset, copy);
3593c5f
+			memcpy(to, rfv_buf, copy);
3593c5f
 		else
3593c5f
 			skb->csum = csum_block_add(
3593c5f
 				skb->csum,
3593c5f
-				csum_partial_copy_nocheck(rfv->c + offset,
3593c5f
-							  to, copy, 0),
3593c5f
+				csum_partial_copy_nocheck(rfv_buf, to, copy, 0),
3593c5f
 				odd);
3593c5f
3593c5f
 		odd = 0;
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From f38cdd5d461ce686d201e41242fd626641e7253d Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:54:02 -0800
3593c5f
Subject: [PATCH 14/19] ipv4: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'offset' may be a user controlled value
3593c5f
that is used as a data dependency reading from a raw_frag_vec buffer.
3593c5f
In order to avoid potential leaks of kernel memory values, block
3593c5f
speculative execution of the instruction stream that could issue further
3593c5f
reads based on an invalid '*(rfv->c + offset)' value.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: "David S. Miller" <davem@davemloft.net>
3593c5f
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
3593c5f
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
3593c5f
Cc: netdev@vger.kernel.org
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 net/ipv4/raw.c | 9 +++++----
3593c5f
 1 file changed, 5 insertions(+), 4 deletions(-)
3593c5f
3593c5f
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
3593c5f
index 125c1eab3eaa..f72b20131a15 100644
3593c5f
--- a/net/ipv4/raw.c
3593c5f
+++ b/net/ipv4/raw.c
3593c5f
@@ -57,6 +57,7 @@
3593c5f
 #include <linux/in_route.h>
3593c5f
 #include <linux/route.h>
3593c5f
 #include <linux/skbuff.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
 #include <linux/igmp.h>
3593c5f
 #include <net/net_namespace.h>
3593c5f
 #include <net/dst.h>
3593c5f
@@ -472,17 +473,17 @@ static int raw_getfrag(void *from, char *to, int offset, int len, int odd,
3593c5f
 		       struct sk_buff *skb)
3593c5f
 {
3593c5f
 	struct raw_frag_vec *rfv = from;
3593c5f
+	char *rfv_buf;
3593c5f
3593c5f
-	if (offset < rfv->hlen) {
3593c5f
+	if ((rfv_buf = nospec_array_ptr(rfv->hdr.c, offset, rfv->hlen))) {
3593c5f
 		int copy = min(rfv->hlen - offset, len);
3593c5f
3593c5f
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
3593c5f
-			memcpy(to, rfv->hdr.c + offset, copy);
3593c5f
+			memcpy(to, rfv_buf, copy);
3593c5f
 		else
3593c5f
 			skb->csum = csum_block_add(
3593c5f
 				skb->csum,
3593c5f
-				csum_partial_copy_nocheck(rfv->hdr.c + offset,
3593c5f
-							  to, copy, 0),
3593c5f
+				csum_partial_copy_nocheck(rfv_buf, to, copy, 0),
3593c5f
 				odd);
3593c5f
3593c5f
 		odd = 0;
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From 07a715cb9cd9e4e8bac7204a2462803bfe7ae259 Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:54:04 -0800
3593c5f
Subject: [PATCH 15/19] vfs, fdtable: prevent bounds-check bypass via
3593c5f
 speculative execution
3593c5f
3593c5f
Expectedly, static analysis reports that 'fd' is a user controlled value
3593c5f
that is used as a data dependency to read from the 'fdt->fd' array.  In
3593c5f
order to avoid potential leaks of kernel memory values, block
3593c5f
speculative execution of the instruction stream that could issue reads
3593c5f
based on an invalid 'file *' returned from __fcheck_files.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: Al Viro <viro@zeniv.linux.org.uk>
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 include/linux/fdtable.h | 5 +++--
3593c5f
 1 file changed, 3 insertions(+), 2 deletions(-)
3593c5f
3593c5f
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
3593c5f
index 1c65817673db..4a147c5c2533 100644
3593c5f
--- a/include/linux/fdtable.h
3593c5f
+++ b/include/linux/fdtable.h
3593c5f
@@ -81,9 +81,10 @@ struct dentry;
3593c5f
 static inline struct file *__fcheck_files(struct files_struct *files, unsigned int fd)
3593c5f
 {
3593c5f
 	struct fdtable *fdt = rcu_dereference_raw(files->fdt);
3593c5f
+	struct file __rcu **fdp;
3593c5f
3593c5f
-	if (fd < fdt->max_fds)
3593c5f
-		return rcu_dereference_raw(fdt->fd[fd]);
3593c5f
+	if ((fdp = nospec_array_ptr(fdt->fd, fd, fdt->max_fds)))
3593c5f
+		return rcu_dereference_raw(*fdp);
3593c5f
 	return NULL;
3593c5f
 }
3593c5f
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From e5ef1fdb08b0d2ae0af3f725a6c4a3394af538fe Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:54:05 -0800
3593c5f
Subject: [PATCH 16/19] net: mpls: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'index' may be a user controlled value that
3593c5f
is used as a data dependency reading 'rt' from the 'platform_label'
3593c5f
array.  In order to avoid potential leaks of kernel memory values, block
3593c5f
speculative execution of the instruction stream that could issue further
3593c5f
reads based on an invalid 'rt' value.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: "David S. Miller" <davem@davemloft.net>
3593c5f
Cc: Eric W. Biederman <ebiederm@xmission.com>
3593c5f
Cc: netdev@vger.kernel.org
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 net/mpls/af_mpls.c | 12 +++++++-----
3593c5f
 1 file changed, 7 insertions(+), 5 deletions(-)
3593c5f
3593c5f
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
3593c5f
index 8ca9915befc8..ebcf0e246cfe 100644
3593c5f
--- a/net/mpls/af_mpls.c
3593c5f
+++ b/net/mpls/af_mpls.c
3593c5f
@@ -8,6 +8,7 @@
3593c5f
 #include <linux/ipv6.h>
3593c5f
 #include <linux/mpls.h>
3593c5f
 #include <linux/netconf.h>
3593c5f
+#include <linux/compiler.h>
3593c5f
 #include <linux/vmalloc.h>
3593c5f
 #include <linux/percpu.h>
3593c5f
 #include <net/ip.h>
3593c5f
@@ -77,12 +78,13 @@ static void rtmsg_lfib(int event, u32 label, struct mpls_route *rt,
3593c5f
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
3593c5f
 {
3593c5f
 	struct mpls_route *rt = NULL;
3593c5f
+	struct mpls_route __rcu **platform_label =
3593c5f
+		rcu_dereference(net->mpls.platform_label);
3593c5f
+	struct mpls_route __rcu **rtp;
3593c5f
3593c5f
-	if (index < net->mpls.platform_labels) {
3593c5f
-		struct mpls_route __rcu **platform_label =
3593c5f
-			rcu_dereference(net->mpls.platform_label);
3593c5f
-		rt = rcu_dereference(platform_label[index]);
3593c5f
-	}
3593c5f
+	if ((rtp = nospec_array_ptr(platform_label, index,
3593c5f
+					net->mpls.platform_labels)))
3593c5f
+		rt = rcu_dereference(*rtp);
3593c5f
 	return rt;
3593c5f
 }
3593c5f
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From 276b18c636de3afc89571198b22b518473ce2b2a Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:54:07 -0800
3593c5f
Subject: [PATCH 17/19] udf: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'eahd->appAttrLocation' and
3593c5f
'eahd->impAttrLocation' may be a user controlled values that are used as
3593c5f
data dependencies for calculating source and destination buffers for
3593c5f
memmove operations. In order to avoid potential leaks of kernel memory
3593c5f
values, block speculative execution of the instruction stream that could
3593c5f
issue further reads based on invalid 'aal' or 'ial' values.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: Jan Kara <jack@suse.com>
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 fs/udf/misc.c | 39 +++++++++++++++++++++------------------
3593c5f
 1 file changed, 21 insertions(+), 18 deletions(-)
3593c5f
3593c5f
diff --git a/fs/udf/misc.c b/fs/udf/misc.c
3593c5f
index 401e64cde1be..9403160822de 100644
3593c5f
--- a/fs/udf/misc.c
3593c5f
+++ b/fs/udf/misc.c
3593c5f
@@ -51,6 +51,8 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
3593c5f
 	int offset;
3593c5f
 	uint16_t crclen;
3593c5f
 	struct udf_inode_info *iinfo = UDF_I(inode);
3593c5f
+	uint8_t *ea_dst, *ea_src;
3593c5f
+	uint32_t aal, ial;
3593c5f
3593c5f
 	ea = iinfo->i_ext.i_data;
3593c5f
 	if (iinfo->i_lenEAttr) {
3593c5f
@@ -100,33 +102,34 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
3593c5f
3593c5f
 		offset = iinfo->i_lenEAttr;
3593c5f
 		if (type < 2048) {
3593c5f
-			if (le32_to_cpu(eahd->appAttrLocation) <
3593c5f
-					iinfo->i_lenEAttr) {
3593c5f
-				uint32_t aal =
3593c5f
-					le32_to_cpu(eahd->appAttrLocation);
3593c5f
-				memmove(&ea[offset - aal + size],
3593c5f
-					&ea[aal], offset - aal);
3593c5f
+			aal = le32_to_cpu(eahd->appAttrLocation);
3593c5f
+			if ((ea_dst = nospec_array_ptr(ea, offset - aal + size,
3593c5f
+						       iinfo->i_lenEAttr)) &&
3593c5f
+			    (ea_src = nospec_array_ptr(ea, aal,
3593c5f
+						       iinfo->i_lenEAttr))) {
3593c5f
+				memmove(ea_dst, ea_src, offset - aal);
3593c5f
 				offset -= aal;
3593c5f
 				eahd->appAttrLocation =
3593c5f
 						cpu_to_le32(aal + size);
3593c5f
 			}
3593c5f
-			if (le32_to_cpu(eahd->impAttrLocation) <
3593c5f
-					iinfo->i_lenEAttr) {
3593c5f
-				uint32_t ial =
3593c5f
-					le32_to_cpu(eahd->impAttrLocation);
3593c5f
-				memmove(&ea[offset - ial + size],
3593c5f
-					&ea[ial], offset - ial);
3593c5f
+
3593c5f
+			ial = le32_to_cpu(eahd->impAttrLocation);
3593c5f
+			if ((ea_dst = nospec_array_ptr(ea, offset - ial + size,
3593c5f
+						       iinfo->i_lenEAttr)) &&
3593c5f
+			    (ea_src = nospec_array_ptr(ea, ial,
3593c5f
+						       iinfo->i_lenEAttr))) {
3593c5f
+				memmove(ea_dst, ea_src, offset - ial);
3593c5f
 				offset -= ial;
3593c5f
 				eahd->impAttrLocation =
3593c5f
 						cpu_to_le32(ial + size);
3593c5f
 			}
3593c5f
 		} else if (type < 65536) {
3593c5f
-			if (le32_to_cpu(eahd->appAttrLocation) <
3593c5f
-					iinfo->i_lenEAttr) {
3593c5f
-				uint32_t aal =
3593c5f
-					le32_to_cpu(eahd->appAttrLocation);
3593c5f
-				memmove(&ea[offset - aal + size],
3593c5f
-					&ea[aal], offset - aal);
3593c5f
+			aal = le32_to_cpu(eahd->appAttrLocation);
3593c5f
+			if ((ea_dst = nospec_array_ptr(ea, offset - aal + size,
3593c5f
+						       iinfo->i_lenEAttr)) &&
3593c5f
+			    (ea_src = nospec_array_ptr(ea, aal,
3593c5f
+						       iinfo->i_lenEAttr))) {
3593c5f
+				memmove(ea_dst, ea_src, offset - aal);
3593c5f
 				offset -= aal;
3593c5f
 				eahd->appAttrLocation =
3593c5f
 						cpu_to_le32(aal + size);
3593c5f
-- 
3593c5f
2.14.3
3593c5f
3593c5f
From e13d6b8e1e65dc93044b72a84990094bb4f7b94c Mon Sep 17 00:00:00 2001
3593c5f
From: Dan Williams <dan.j.williams@intel.com>
3593c5f
Date: Wed, 3 Jan 2018 13:54:09 -0800
3593c5f
Subject: [PATCH 18/19] userns: prevent bounds-check bypass via speculative
3593c5f
 execution
3593c5f
3593c5f
Static analysis reports that 'pos' may be a user controlled value that
3593c5f
is used as a data dependency determining which extent to return out of
3593c5f
'map'. In order to avoid potential leaks of kernel memory values, block
3593c5f
speculative execution of the instruction stream that could issue further
3593c5f
reads based on an invalid speculative result from 'm_start()'.
3593c5f
3593c5f
Based on an original patch by Elena Reshetova.
3593c5f
3593c5f
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
3593c5f
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
3593c5f
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
3593c5f
---
3593c5f
 kernel/user_namespace.c | 10 ++++------
3593c5f
 1 file changed, 4 insertions(+), 6 deletions(-)
3593c5f
3593c5f
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
3593c5f
index 246d4d4ce5c7..e958f2e5c061 100644
3593c5f
--- a/kernel/user_namespace.c
3593c5f
+++ b/kernel/user_namespace.c
3593c5f
@@ -648,15 +648,13 @@ static void *m_start(struct seq_file *seq, loff_t *ppos,
3593c5f
 {
3593c5f
 	loff_t pos = *ppos;
3593c5f
 	unsigned extents = map->nr_extents;
3593c5f
-	smp_rmb();
3593c5f
3593c5f
-	if (pos >= extents)
3593c5f
-		return NULL;
3593c5f
+	/* paired with smp_wmb in map_write */
3593c5f
+	smp_rmb();
3593c5f
3593c5f
 	if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
3593c5f
-		return &map->extent[pos];
3593c5f
-
3593c5f
-	return &map->forward[pos];
3593c5f
+		return nospec_array_ptr(map->extent, pos, extents);
3593c5f
+	return nospec_array_ptr(map->forward, pos, extents);
3593c5f
 }
3593c5f
3593c5f
 static void *uid_m_start(struct seq_file *seq, loff_t *ppos)
3593c5f
-- 
3593c5f
2.14.3