All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/13] spectre variant1 mitigations for tip/x86/pti
@ 2018-01-30  1:02 ` Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: Mark Rutland, Cyril Novikov, kernel-hardening, Peter Zijlstra,
	Catalin Marinas, Will Deacon, H. Peter Anvin, Jiri Slaby,
	Elena Reshetova, linux-arch, Andi Kleen, Jonathan Corbet, x86,
	Russell King, Ingo Molnar, Andrew Honig, alan, Tom Lendacky,
	Kees Cook, Al Viro, Andy Lutomirski, Jim Mattson,
	Christian Lamparter, gregkh, linux-wireless, linux-kernel,
	Paolo Bonzini, Johannes Berg, torvalds, David S. Miller

Hi Thomas, Ingo,

Here is another spin of the Spectre variant1 mitigations.

Changes since v5 [1]:
* Use the _nospec suffix for all new infrastructure, i.e.
  s/ifence/barrier_nospec/, s/array_idx/array_index_nospec/,
  and s/array_idx_mask/array_index_mask_nospec/. (Ingo)

* Fix up array_index_mask_nospec() to have a proper kernel doc comment
  (Thomas)

* Fix up copyright attribution in include/linux/nospec.h (Ingo)

* Spell out 'index' and 'size' throughout the patch set rather than
  'idx' and 'sz'. (Ingo).

* Clarify placement of barrier_nospec() relative to stac() in
  __uaccess_begin_nospec() (Ingo)

* Drop the syscall fast path elimination patch out of this series since
  Andy is handling that separately. (Andy)

* Simplify the x86 array_index_mask_nospec() assembly, no need for a
  separate 32-bit version (Ingo)

* Clarify that the 'cmp, sbb' sequence in the get_user_<size> variants
  are effectively open coded array_index_nospec() instances where the
  array base is the user pointer and the array limit is the task address
  limit. (Ingo)

* Replace '<function identifier>' with <function identifier>()
  throughout the series. (Ingo)

* Comment and whitespace fixups in asm/barrier.h (Ingo)

* Split the definition of barrier_nospec() into its own patch separate
  from its new usages with __uaccess_begin_nospec(). (Ingo)

* Split the __uaccess_begin_nospec() patch into one that cleans up open
  coded stac/clac usage and one that uses the new
  __uaccess_begin_nospec() helper. (Ingo)

* Change the contents of the 'bug/spectre_v1' sysfs file to:
  "Mitigation: __user pointer sanitization" since these changes do raise
  the kernel's defenses. (Ingo)

[1]: https://www.spinics.net/lists/linux-arch/msg44193.html

---

Dan Williams (12):
      array_index_nospec: sanitize speculative array de-references
      x86: implement array_index_mask_nospec
      x86: introduce barrier_nospec
      x86: introduce __uaccess_begin_nospec
      x86, usercopy: replace open coded stac/clac with __uaccess_{begin,end}
      x86, __get_user: use __uaccess_begin_nospec
      x86, get_user: use pointer masking to limit speculation
      x86: sanitize syscall table de-references under speculation
      vfs, fdtable: prevent bounds-check bypass via speculative execution
      kvm, x86: update spectre-v1 mitigation
      nl80211: sanitize array index in parse_txq_params
      x86/spectre: report get_user mitigation for spectre_v1

Mark Rutland (1):
      Documentation: document array_index_nospec


 Documentation/speculation.txt     |   90 +++++++++++++++++++++++++++++++++++++
 arch/x86/entry/common.c           |    5 ++
 arch/x86/include/asm/barrier.h    |   28 ++++++++++++
 arch/x86/include/asm/msr.h        |    3 -
 arch/x86/include/asm/uaccess.h    |   15 +++++-
 arch/x86/include/asm/uaccess_32.h |    6 +-
 arch/x86/include/asm/uaccess_64.h |   12 ++---
 arch/x86/kernel/cpu/bugs.c        |    2 -
 arch/x86/kvm/vmx.c                |   14 ++++--
 arch/x86/lib/getuser.S            |   10 ++++
 arch/x86/lib/usercopy_32.c        |    8 ++-
 include/linux/fdtable.h           |    5 ++
 include/linux/nospec.h            |   72 ++++++++++++++++++++++++++++++
 net/wireless/nl80211.c            |    9 ++--
 14 files changed, 251 insertions(+), 28 deletions(-)
 create mode 100644 Documentation/speculation.txt
 create mode 100644 include/linux/nospec.h

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v6 00/13] spectre variant1 mitigations for tip/x86/pti
@ 2018-01-30  1:02 ` Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: Mark Rutland, Cyril Novikov, kernel-hardening, Peter Zijlstra,
	Catalin Marinas, Will Deacon, H. Peter Anvin, Jiri Slaby,
	Elena Reshetova, linux-arch, Andi Kleen, Jonathan Corbet, x86,
	Russell King, Ingo Molnar, Andrew Honig, alan, Tom Lendacky,
	Kees Cook, Al Viro, Andy Lutomirski, Jim Mattson

Hi Thomas, Ingo,

Here is another spin of the Spectre variant1 mitigations.

Changes since v5 [1]:
* Use the _nospec suffix for all new infrastructure, i.e.
  s/ifence/barrier_nospec/, s/array_idx/array_index_nospec/,
  and s/array_idx_mask/array_index_mask_nospec/. (Ingo)

* Fix up array_index_mask_nospec() to have a proper kernel doc comment
  (Thomas)

* Fix up copyright attribution in include/linux/nospec.h (Ingo)

* Spell out 'index' and 'size' throughout the patch set rather than
  'idx' and 'sz'. (Ingo).

* Clarify placement of barrier_nospec() relative to stac() in
  __uaccess_begin_nospec() (Ingo)

* Drop the syscall fast path elimination patch out of this series since
  Andy is handling that separately. (Andy)

* Simplify the x86 array_index_mask_nospec() assembly, no need for a
  separate 32-bit version (Ingo)

* Clarify that the 'cmp, sbb' sequence in the get_user_<size> variants
  are effectively open coded array_index_nospec() instances where the
  array base is the user pointer and the array limit is the task address
  limit. (Ingo)

* Replace '<function identifier>' with <function identifier>()
  throughout the series. (Ingo)

* Comment and whitespace fixups in asm/barrier.h (Ingo)

* Split the definition of barrier_nospec() into its own patch separate
  from its new usages with __uaccess_begin_nospec(). (Ingo)

* Split the __uaccess_begin_nospec() patch into one that cleans up open
  coded stac/clac usage and one that uses the new
  __uaccess_begin_nospec() helper. (Ingo)

* Change the contents of the 'bug/spectre_v1' sysfs file to:
  "Mitigation: __user pointer sanitization" since these changes do raise
  the kernel's defenses. (Ingo)

[1]: https://www.spinics.net/lists/linux-arch/msg44193.html

---

Dan Williams (12):
      array_index_nospec: sanitize speculative array de-references
      x86: implement array_index_mask_nospec
      x86: introduce barrier_nospec
      x86: introduce __uaccess_begin_nospec
      x86, usercopy: replace open coded stac/clac with __uaccess_{begin,end}
      x86, __get_user: use __uaccess_begin_nospec
      x86, get_user: use pointer masking to limit speculation
      x86: sanitize syscall table de-references under speculation
      vfs, fdtable: prevent bounds-check bypass via speculative execution
      kvm, x86: update spectre-v1 mitigation
      nl80211: sanitize array index in parse_txq_params
      x86/spectre: report get_user mitigation for spectre_v1

Mark Rutland (1):
      Documentation: document array_index_nospec


 Documentation/speculation.txt     |   90 +++++++++++++++++++++++++++++++++++++
 arch/x86/entry/common.c           |    5 ++
 arch/x86/include/asm/barrier.h    |   28 ++++++++++++
 arch/x86/include/asm/msr.h        |    3 -
 arch/x86/include/asm/uaccess.h    |   15 +++++-
 arch/x86/include/asm/uaccess_32.h |    6 +-
 arch/x86/include/asm/uaccess_64.h |   12 ++---
 arch/x86/kernel/cpu/bugs.c        |    2 -
 arch/x86/kvm/vmx.c                |   14 ++++--
 arch/x86/lib/getuser.S            |   10 ++++
 arch/x86/lib/usercopy_32.c        |    8 ++-
 include/linux/fdtable.h           |    5 ++
 include/linux/nospec.h            |   72 ++++++++++++++++++++++++++++++
 net/wireless/nl80211.c            |    9 ++--
 14 files changed, 251 insertions(+), 28 deletions(-)
 create mode 100644 Documentation/speculation.txt
 create mode 100644 include/linux/nospec.h

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v6 01/13] Documentation: document array_index_nospec
  2018-01-30  1:02 ` Dan Williams
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:33   ` [tip:x86/pti] Documentation: Document array_index_nospec tip-bot for Mark Rutland
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: Mark Rutland, linux-arch, Kees Cook, Jonathan Corbet,
	Peter Zijlstra, gregkh, kernel-hardening, Will Deacon,
	linux-kernel, torvalds, alan

From: Mark Rutland <mark.rutland@arm.com>

Document the rationale and usage of the new array_index_nospec() helper.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Peter Zijlstra <peterz@infradead.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 Documentation/speculation.txt |   90 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)
 create mode 100644 Documentation/speculation.txt

diff --git a/Documentation/speculation.txt b/Documentation/speculation.txt
new file mode 100644
index 000000000000..e9e6cbae2841
--- /dev/null
+++ b/Documentation/speculation.txt
@@ -0,0 +1,90 @@
+This document explains potential effects of speculation, and how undesirable
+effects can be mitigated portably using common APIs.
+
+===========
+Speculation
+===========
+
+To improve performance and minimize average latencies, many contemporary CPUs
+employ speculative execution techniques such as branch prediction, performing
+work which may be discarded at a later stage.
+
+Typically speculative execution cannot be observed from architectural state,
+such as the contents of registers. However, in some cases it is possible to
+observe its impact on microarchitectural state, such as the presence or
+absence of data in caches. Such state may form side-channels which can be
+observed to extract secret information.
+
+For example, in the presence of branch prediction, it is possible for bounds
+checks to be ignored by code which is speculatively executed. Consider the
+following code:
+
+	int load_array(int *array, unsigned int index)
+	{
+		if (index >= MAX_ARRAY_ELEMS)
+			return 0;
+		else
+			return array[index];
+	}
+
+Which, on arm64, may be compiled to an assembly sequence such as:
+
+	CMP	<index>, #MAX_ARRAY_ELEMS
+	B.LT	less
+	MOV	<returnval>, #0
+	RET
+  less:
+	LDR	<returnval>, [<array>, <index>]
+	RET
+
+It is possible that a CPU mis-predicts the conditional branch, and
+speculatively loads array[index], even if index >= MAX_ARRAY_ELEMS. This
+value will subsequently be discarded, but the speculated load may affect
+microarchitectural state which can be subsequently measured.
+
+More complex sequences involving multiple dependent memory accesses may
+result in sensitive information being leaked. Consider the following
+code, building on the prior example:
+
+	int load_dependent_arrays(int *arr1, int *arr2, int index)
+	{
+		int val1, val2,
+
+		val1 = load_array(arr1, index);
+		val2 = load_array(arr2, val1);
+
+		return val2;
+	}
+
+Under speculation, the first call to load_array() may return the value
+of an out-of-bounds address, while the second call will influence
+microarchitectural state dependent on this value. This may provide an
+arbitrary read primitive.
+
+====================================
+Mitigating speculation side-channels
+====================================
+
+The kernel provides a generic API to ensure that bounds checks are
+respected even under speculation. Architectures which are affected by
+speculation-based side-channels are expected to implement these
+primitives.
+
+The array_index_nospec() helper in <linux/nospec.h> can be used to
+prevent information from being leaked via side-channels.
+
+A call to array_index_nospec(index, size) returns a sanitized index
+value that is bounded to [0, size) even under cpu speculation
+conditions.
+
+This can be used to protect the earlier load_array() example:
+
+	int load_array(int *array, unsigned int index)
+	{
+		if (index >= MAX_ARRAY_ELEMS)
+			return 0;
+		else {
+			index = array_index_nospec(index, MAX_ARRAY_ELEMS);
+			return array[index];
+		}
+	}

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 02/13] array_index_nospec: sanitize speculative array de-references
  2018-01-30  1:02 ` Dan Williams
  (?)
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:34   ` [tip:x86/pti] array_index_nospec: Sanitize " tip-bot for Dan Williams
  2018-02-16  8:55   ` [PATCH v6 02/13] array_index_nospec: sanitize " Christian Borntraeger
  -1 siblings, 2 replies; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, Cyril Novikov, kernel-hardening, Peter Zijlstra,
	Catalin Marinas, x86, Will Deacon, Russell King, linux-kernel,
	Ingo Molnar, gregkh, H. Peter Anvin, torvalds, alan

array_index_nospec() is proposed as a generic mechanism to mitigate
against Spectre-variant-1 attacks, i.e. an attack that bypasses boundary
checks via speculative execution. The array_index_nospec()
implementation is expected to be safe for current generation CPUs across
multiple architectures (ARM, x86).

Based on an original implementation by Linus Torvalds, tweaked to remove
speculative flows by Alexei Starovoitov, and tweaked again by Linus to
introduce an x86 assembly implementation for the mask generation.

Co-developed-by: Linus Torvalds <torvalds@linux-foundation.org>
Co-developed-by: Alexei Starovoitov <ast@kernel.org>
Suggested-by: Cyril Novikov <cnovikov@lynx.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 include/linux/nospec.h |   72 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)
 create mode 100644 include/linux/nospec.h

diff --git a/include/linux/nospec.h b/include/linux/nospec.h
new file mode 100644
index 000000000000..cf7be4bbcf17
--- /dev/null
+++ b/include/linux/nospec.h
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright(c) 2018 Linus Torvalds. All rights reserved.
+// Copyright(c) 2018 Alexei Starovoitov. All rights reserved.
+// Copyright(c) 2018 Intel Corporation. All rights reserved.
+
+#ifndef _LINUX_NOSPEC_H
+#define _LINUX_NOSPEC_H
+
+/**
+ * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
+ * @index: array element index
+ * @size: number of elements in array
+ *
+ * When @index is out of bounds (@index >= @size), the sign bit will be
+ * set.  Extend the sign bit to all bits and invert, giving a result of
+ * zero for an out of bounds index, or ~0 if within bounds [0, @size).
+ */
+#ifndef array_index_mask_nospec
+static inline unsigned long array_index_mask_nospec(unsigned long index,
+		unsigned long size)
+{
+	/*
+	 * Warn developers about inappropriate array_index_nospec() usage.
+	 *
+	 * Even if the CPU speculates past the WARN_ONCE branch, the
+	 * sign bit of @index is taken into account when generating the
+	 * mask.
+	 *
+	 * This warning is compiled out when the compiler can infer that
+	 * @index and @size are less than LONG_MAX.
+	 */
+	if (WARN_ONCE(index > LONG_MAX || size > LONG_MAX,
+			"array_index_nospec() limited to range of [0, LONG_MAX]\n"))
+		return 0;
+
+	/*
+	 * Always calculate and emit the mask even if the compiler
+	 * thinks the mask is not needed. The compiler does not take
+	 * into account the value of @index under speculation.
+	 */
+	OPTIMIZER_HIDE_VAR(index);
+	return ~(long)(index | (size - 1UL - index)) >> (BITS_PER_LONG - 1);
+}
+#endif
+
+/*
+ * array_index_nospec - sanitize an array index after a bounds check
+ *
+ * For a code sequence like:
+ *
+ *     if (index < size) {
+ *         index = array_index_nospec(index, size);
+ *         val = array[index];
+ *     }
+ *
+ * ...if the CPU speculates past the bounds check then
+ * array_index_nospec() will clamp the index within the range of [0,
+ * size).
+ */
+#define array_index_nospec(index, size)					\
+({									\
+	typeof(index) _i = (index);					\
+	typeof(size) _s = (size);					\
+	unsigned long _mask = array_index_mask_nospec(_i, _s);		\
+									\
+	BUILD_BUG_ON(sizeof(_i) > sizeof(long));			\
+	BUILD_BUG_ON(sizeof(_s) > sizeof(long));			\
+									\
+	_i &= _mask;							\
+	_i;								\
+})
+#endif /* _LINUX_NOSPEC_H */

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 03/13] x86: implement array_index_mask_nospec
  2018-01-30  1:02 ` Dan Williams
                   ` (2 preceding siblings ...)
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:34   ` [tip:x86/pti] x86: Implement array_index_mask_nospec tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, kernel-hardening, gregkh, x86, linux-kernel,
	Ingo Molnar, H. Peter Anvin, torvalds, alan

array_index_nospec() uses a mask to sanitize user controllable array
indexes, i.e. generate a 0 mask if 'index' >= 'size', and a ~0 mask
otherwise. While the default array_index_mask_nospec() handles the
carry-bit from the (index - size) result in software. The x86
array_index_mask_nospec() does the same, but the carry-bit is handled in
the processor CF flag without conditional instructions in the control
flow.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/include/asm/barrier.h |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
index 01727dbc294a..551ccbe07c0f 100644
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -24,6 +24,30 @@
 #define wmb()	asm volatile("sfence" ::: "memory")
 #endif
 
+/**
+ * array_index_mask_nospec() - generate a mask that is ~0UL when the
+ * 	bounds check succeeds and 0 otherwise
+ * @index: array element index
+ * @size: number of elements in array
+ *
+ * Returns:
+ *     0 - (index < size)
+ */
+static inline unsigned long array_index_mask_nospec(unsigned long index,
+		unsigned long size)
+{
+	unsigned long mask;
+
+	asm ("cmp %1,%2; sbb %0,%0;"
+			:"=r" (mask)
+			:"r"(size),"r" (index)
+			:"cc");
+	return mask;
+}
+
+/* Override the default implementation from linux/nospec.h. */
+#define array_index_mask_nospec array_index_mask_nospec
+
 #ifdef CONFIG_X86_PPRO_FENCE
 #define dma_rmb()	rmb()
 #else

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 04/13] x86: introduce barrier_nospec
  2018-01-30  1:02 ` Dan Williams
                   ` (3 preceding siblings ...)
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:35   ` [tip:x86/pti] x86: Introduce barrier_nospec tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, Tom Lendacky, Andi Kleen, Kees Cook,
	kernel-hardening, gregkh, x86, linux-kernel, Ingo Molnar,
	Al Viro, H. Peter Anvin, torvalds, alan

Rename the open coded form of this instruction sequence from
rdtsc_ordered() into a generic barrier primitive, barrier_nospec().

One of the mitigations for Spectre variant1 vulnerabilities is to fence
speculative execution after successfully validating a bounds check. I.e.
force the result of a bounds check to resolve in the instruction
pipeline to ensure speculative execution honors that result before
potentially operating on out-of-bounds data.

There are no functional changes in this patch.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Suggested-by: Ingo Molnar <mingo@redhat.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/include/asm/barrier.h |    4 ++++
 arch/x86/include/asm/msr.h     |    3 +--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
index 551ccbe07c0f..1e7c955b6303 100644
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -48,6 +48,10 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
 /* Override the default implementation from linux/nospec.h. */
 #define array_index_mask_nospec array_index_mask_nospec
 
+/* Prevent speculative execution past this barrier. */
+#define barrier_nospec() alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC, \
+					   "lfence", X86_FEATURE_LFENCE_RDTSC)
+
 #ifdef CONFIG_X86_PPRO_FENCE
 #define dma_rmb()	rmb()
 #else
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 07962f5f6fba..30df295f6d94 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -214,8 +214,7 @@ static __always_inline unsigned long long rdtsc_ordered(void)
 	 * that some other imaginary CPU is updating continuously with a
 	 * time stamp.
 	 */
-	alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC,
-			  "lfence", X86_FEATURE_LFENCE_RDTSC);
+	barrier_nospec();
 	return rdtsc();
 }
 

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 05/13] x86: introduce __uaccess_begin_nospec
  2018-01-30  1:02 ` Dan Williams
                   ` (4 preceding siblings ...)
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:35   ` [tip:x86/pti] x86: Introduce __uaccess_begin_nospec() and uaccess_try_nospec tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, Tom Lendacky, Andi Kleen, Kees Cook,
	kernel-hardening, gregkh, x86, linux-kernel, Ingo Molnar,
	Al Viro, H. Peter Anvin, torvalds, alan

For __get_user() paths, do not allow the kernel to speculate on the
value of a user controlled pointer. In addition to the 'stac'
instruction for Supervisor Mode Access Protection (SMAP), a
barrier_nospec() causes the access_ok() result to resolve in the
pipeline before the CPU might take any speculative action on the pointer
value. Given the cost of 'stac' the speculation barrier is placed after
'stac' to hopefully overlap the cost of disabling SMAP with the cost of
flushing the instruction pipeline.

Since __get_user is a major kernel interface that deals with user
controlled pointers, the __uaccess_begin_nospec() mechanism will prevent
speculative execution past an access_ok() permission check. While
speculative execution past access_ok() is not enough to lead to a kernel
memory leak, it is a necessary precondition.

To be clear, __uaccess_begin_nospec() is addressing a class of potential
problems near __get_user() usages.

Note, that while the barrier_nospec() in __uaccess_begin_nospec() is
used to protect __get_user(), pointer masking similar to
array_index_nospec() will be used for get_user() since it incorporates a
bounds check near the usage.

There are no functional changes in this patch.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Suggested-by: Ingo Molnar <mingo@redhat.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/include/asm/uaccess.h |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 574dff4d2913..663e9bde9fc9 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -124,6 +124,11 @@ extern int __get_user_bad(void);
 
 #define __uaccess_begin() stac()
 #define __uaccess_end()   clac()
+#define __uaccess_begin_nospec()	\
+({					\
+	stac();				\
+	barrier_nospec();		\
+})
 
 /*
  * This is a type: either unsigned long, if the argument fits into
@@ -487,6 +492,10 @@ struct __large_struct { unsigned long buf[100]; };
 	__uaccess_begin();						\
 	barrier();
 
+#define uaccess_try_nospec do {						\
+	current->thread.uaccess_err = 0;				\
+	__uaccess_begin_nospec();					\
+
 #define uaccess_catch(err)						\
 	__uaccess_end();						\
 	(err) |= (current->thread.uaccess_err ? -EFAULT : 0);		\

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 06/13] x86, usercopy: replace open coded stac/clac with __uaccess_{begin, end}
  2018-01-30  1:02 ` Dan Williams
                   ` (5 preceding siblings ...)
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:35   ` [tip:x86/pti] x86/usercopy: Replace " tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, Tom Lendacky, Kees Cook, kernel-hardening, gregkh,
	x86, linux-kernel, Ingo Molnar, Al Viro, H. Peter Anvin,
	torvalds, alan

In preparation for converting some __uaccess_begin() instances to
__uacess_begin_nospec(), make sure all 'from user' uaccess paths are
using the _begin(), _end() helpers rather than open-coded stac() and
clac().

There are no functional changes in this patch.

Suggested-by: Ingo Molnar <mingo@redhat.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/lib/usercopy_32.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 1b377f734e64..de3436719e26 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -331,12 +331,12 @@ do {									\
 
 unsigned long __copy_user_ll(void *to, const void *from, unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
 		n = __copy_user_intel(to, from, n);
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_user_ll);
@@ -344,7 +344,7 @@ EXPORT_SYMBOL(__copy_user_ll);
 unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
 					unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
 		n = __copy_user_intel_nocache(to, from, n);
@@ -353,7 +353,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
 #else
 	__copy_user(to, from, n);
 #endif
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 07/13] x86, __get_user: use __uaccess_begin_nospec
  2018-01-30  1:02 ` Dan Williams
                   ` (6 preceding siblings ...)
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:36   ` [tip:x86/pti] x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, Andi Kleen, Kees Cook, kernel-hardening, gregkh, x86,
	linux-kernel, Ingo Molnar, Al Viro, H. Peter Anvin, torvalds,
	alan

Quoting Linus:

    I do think that it would be a good idea to very expressly document
    the fact that it's not that the user access itself is unsafe. I do
    agree that things like "get_user()" want to be protected, but not
    because of any direct bugs or problems with get_user() and friends,
    but simply because get_user() is an excellent source of a pointer
    that is obviously controlled from a potentially attacking user
    space. So it's a prime candidate for then finding _subsequent_
    accesses that can then be used to perturb the cache.

__uaccess_begin_nospec() covers __get_user() and copy_from_iter() where
the limit check is far away from the user pointer de-reference. In those
cases a barrier_nospec() prevents speculation with a potential pointer to
privileged memory.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: x86@kernel.org
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/include/asm/uaccess.h    |    6 +++---
 arch/x86/include/asm/uaccess_32.h |    6 +++---
 arch/x86/include/asm/uaccess_64.h |   12 ++++++------
 arch/x86/lib/usercopy_32.c        |    4 ++--
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 663e9bde9fc9..aae77eb8491c 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -450,7 +450,7 @@ do {									\
 ({									\
 	int __gu_err;							\
 	__inttype(*(ptr)) __gu_val;					\
-	__uaccess_begin();						\
+	__uaccess_begin_nospec();					\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
 	__uaccess_end();						\
 	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
@@ -557,7 +557,7 @@ struct __large_struct { unsigned long buf[100]; };
  *	get_user_ex(...);
  * } get_user_catch(err)
  */
-#define get_user_try		uaccess_try
+#define get_user_try		uaccess_try_nospec
 #define get_user_catch(err)	uaccess_catch(err)
 
 #define get_user_ex(x, ptr)	do {					\
@@ -591,7 +591,7 @@ extern void __cmpxchg_wrong_size(void)
 	__typeof__(ptr) __uval = (uval);				\
 	__typeof__(*(ptr)) __old = (old);				\
 	__typeof__(*(ptr)) __new = (new);				\
-	__uaccess_begin();						\
+	__uaccess_begin_nospec();					\
 	switch (size) {							\
 	case 1:								\
 	{								\
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 72950401b223..ba2dc1930630 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -29,21 +29,21 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long n)
 		switch (n) {
 		case 1:
 			ret = 0;
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_asm_nozero(*(u8 *)to, from, ret,
 					      "b", "b", "=q", 1);
 			__uaccess_end();
 			return ret;
 		case 2:
 			ret = 0;
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_asm_nozero(*(u16 *)to, from, ret,
 					      "w", "w", "=r", 2);
 			__uaccess_end();
 			return ret;
 		case 4:
 			ret = 0;
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_asm_nozero(*(u32 *)to, from, ret,
 					      "l", "k", "=r", 4);
 			__uaccess_end();
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index f07ef3c575db..62546b3a398e 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -55,31 +55,31 @@ raw_copy_from_user(void *dst, const void __user *src, unsigned long size)
 		return copy_user_generic(dst, (__force void *)src, size);
 	switch (size) {
 	case 1:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u8 *)dst, (u8 __user *)src,
 			      ret, "b", "b", "=q", 1);
 		__uaccess_end();
 		return ret;
 	case 2:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u16 *)dst, (u16 __user *)src,
 			      ret, "w", "w", "=r", 2);
 		__uaccess_end();
 		return ret;
 	case 4:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u32 *)dst, (u32 __user *)src,
 			      ret, "l", "k", "=r", 4);
 		__uaccess_end();
 		return ret;
 	case 8:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
 			      ret, "q", "", "=r", 8);
 		__uaccess_end();
 		return ret;
 	case 10:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
 			       ret, "q", "", "=r", 10);
 		if (likely(!ret))
@@ -89,7 +89,7 @@ raw_copy_from_user(void *dst, const void __user *src, unsigned long size)
 		__uaccess_end();
 		return ret;
 	case 16:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
 			       ret, "q", "", "=r", 16);
 		if (likely(!ret))
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index de3436719e26..7add8ba06887 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -331,7 +331,7 @@ do {									\
 
 unsigned long __copy_user_ll(void *to, const void *from, unsigned long n)
 {
-	__uaccess_begin();
+	__uaccess_begin_nospec();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
@@ -344,7 +344,7 @@ EXPORT_SYMBOL(__copy_user_ll);
 unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
 					unsigned long n)
 {
-	__uaccess_begin();
+	__uaccess_begin_nospec();
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
 		n = __copy_user_intel_nocache(to, from, n);

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 08/13] x86, get_user: use pointer masking to limit speculation
  2018-01-30  1:02 ` Dan Williams
                   ` (7 preceding siblings ...)
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:36   ` [tip:x86/pti] x86/get_user: Use " tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, Kees Cook, kernel-hardening, gregkh, x86,
	linux-kernel, Ingo Molnar, Al Viro, Andy Lutomirski,
	H. Peter Anvin, torvalds, alan

Quoting Linus:

    I do think that it would be a good idea to very expressly document
    the fact that it's not that the user access itself is unsafe. I do
    agree that things like "get_user()" want to be protected, but not
    because of any direct bugs or problems with get_user() and friends,
    but simply because get_user() is an excellent source of a pointer
    that is obviously controlled from a potentially attacking user
    space. So it's a prime candidate for then finding _subsequent_
    accesses that can then be used to perturb the cache.

Unlike the __get_user() case get_user() includes the address limit check
near the pointer de-reference. With that locality the speculation can be
mitigated with pointer narrowing rather than a barrier, i.e.
array_index_nospec(). Where the narrowing is performed by:

	cmp %limit, %ptr
	sbb %mask, %mask
	and %mask, %ptr

With respect to speculation the value of %ptr is either less than %limit
or NULL.

Co-developed-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Kees Cook <keescook@chromium.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: x86@kernel.org
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/lib/getuser.S |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index c97d935a29e8..49b167f73215 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -40,6 +40,8 @@ ENTRY(__get_user_1)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 1:	movzbl (%_ASM_AX),%edx
 	xor %eax,%eax
@@ -54,6 +56,8 @@ ENTRY(__get_user_2)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 2:	movzwl -1(%_ASM_AX),%edx
 	xor %eax,%eax
@@ -68,6 +72,8 @@ ENTRY(__get_user_4)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 3:	movl -3(%_ASM_AX),%edx
 	xor %eax,%eax
@@ -83,6 +89,8 @@ ENTRY(__get_user_8)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 4:	movq -7(%_ASM_AX),%rdx
 	xor %eax,%eax
@@ -94,6 +102,8 @@ ENTRY(__get_user_8)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user_8
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 4:	movl -7(%_ASM_AX),%edx
 5:	movl -3(%_ASM_AX),%ecx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 09/13] x86: sanitize syscall table de-references under speculation
  2018-01-30  1:02 ` Dan Williams
                   ` (8 preceding siblings ...)
  (?)
@ 2018-01-30  1:02 ` Dan Williams
  2018-01-30 22:37   ` [tip:x86/pti] x86/syscall: Sanitize " tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:02 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, kernel-hardening, gregkh, x86, linux-kernel,
	Ingo Molnar, Andy Lutomirski, H. Peter Anvin, torvalds, alan

The syscall table base is a user controlled function pointer in kernel
space. Use array_index_nospec() to prevent any out of bounds
speculation. While retpoline prevents speculating into a userspace
directed target it does not stop the pointer de-reference, the concern
is leaking memory relative to the syscall table base, by observing
instruction cache behavior.

Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/entry/common.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 03505ffbe1b6..390abbc4c915 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -21,6 +21,7 @@
 #include <linux/export.h>
 #include <linux/context_tracking.h>
 #include <linux/user-return-notifier.h>
+#include <linux/nospec.h>
 #include <linux/uprobes.h>
 #include <linux/livepatch.h>
 #include <linux/syscalls.h>
@@ -284,7 +285,8 @@ __visible void do_syscall_64(struct pt_regs *regs)
 	 * regs->orig_ax, which changes the behavior of some syscalls.
 	 */
 	if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) {
-		regs->ax = sys_call_table[nr & __SYSCALL_MASK](
+		nr = array_index_nospec(nr & __SYSCALL_MASK, NR_syscalls);
+		regs->ax = sys_call_table[nr](
 			regs->di, regs->si, regs->dx,
 			regs->r10, regs->r8, regs->r9);
 	}
@@ -320,6 +322,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
 	}
 
 	if (likely(nr < IA32_NR_syscalls)) {
+		nr = array_index_nospec(nr, IA32_NR_syscalls);
 		/*
 		 * It's possible that a 32-bit syscall implementation
 		 * takes a 64-bit parameter but nonetheless assumes that

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 10/13] vfs, fdtable: prevent bounds-check bypass via speculative execution
  2018-01-30  1:02 ` Dan Williams
                   ` (9 preceding siblings ...)
  (?)
@ 2018-01-30  1:03 ` Dan Williams
  2018-01-30 22:37   ` [tip:x86/pti] vfs, fdtable: Prevent " tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:03 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, kernel-hardening, gregkh, linux-kernel, Al Viro,
	torvalds, alan

'fd' is a user controlled value that is used as a data dependency to
read from the 'fdt->fd' array.  In order to avoid potential leaks of
kernel memory values, block speculative execution of the instruction
stream that could issue reads based on an invalid 'file *' returned from
__fcheck_files.

Cc: Al Viro <viro@zeniv.linux.org.uk>
Co-developed-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 include/linux/fdtable.h |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 1c65817673db..41615f38bcff 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -10,6 +10,7 @@
 #include <linux/compiler.h>
 #include <linux/spinlock.h>
 #include <linux/rcupdate.h>
+#include <linux/nospec.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/fs.h>
@@ -82,8 +83,10 @@ static inline struct file *__fcheck_files(struct files_struct *files, unsigned i
 {
 	struct fdtable *fdt = rcu_dereference_raw(files->fdt);
 
-	if (fd < fdt->max_fds)
+	if (fd < fdt->max_fds) {
+		fd = array_index_nospec(fd, fdt->max_fds);
 		return rcu_dereference_raw(fdt->fd[fd]);
+	}
 	return NULL;
 }
 

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 11/13] kvm, x86: update spectre-v1 mitigation
  2018-01-30  1:02 ` Dan Williams
                   ` (10 preceding siblings ...)
  (?)
@ 2018-01-30  1:03 ` Dan Williams
  2018-01-31  3:22   ` Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:03 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, kernel-hardening, Andrew Honig, linux-kernel, gregkh,
	Paolo Bonzini, alan, torvalds, Jim Mattson

Commit 75f139aaf896 "KVM: x86: Add memory barrier on vmcs field lookup"
added a raw 'asm("lfence");' to prevent a bounds check bypass of
'vmcs_field_to_offset_table'. We can save an lfence in this path and
just use the common array_index_nospec() helper designed for these types
of fixes.

Cc: Andrew Honig <ahonig@google.com>
Cc: Jim Mattson <jmattson@google.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/kvm/vmx.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 924589c53422..8514186241d2 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -34,6 +34,7 @@
 #include <linux/tboot.h>
 #include <linux/hrtimer.h>
 #include <linux/frame.h>
+#include <linux/nospec.h>
 #include "kvm_cache_regs.h"
 #include "x86.h"
 
@@ -883,13 +884,18 @@ static const unsigned short vmcs_field_to_offset_table[] = {
 
 static inline short vmcs_field_to_offset(unsigned long field)
 {
-	BUILD_BUG_ON(ARRAY_SIZE(vmcs_field_to_offset_table) > SHRT_MAX);
+	const size_t size = ARRAY_SIZE(vmcs_field_to_offset_table);
+	unsigned short offset;
 
-	if (field >= ARRAY_SIZE(vmcs_field_to_offset_table) ||
-	    vmcs_field_to_offset_table[field] == 0)
+	BUILD_BUG_ON(size > SHRT_MAX);
+	if (field >= size)
 		return -ENOENT;
 
-	return vmcs_field_to_offset_table[field];
+	field = array_index_nospec(field, size);
+	offset = vmcs_field_to_offset_table[field];
+	if (offset == 0)
+		return -ENOENT;
+	return offset;
 }
 
 static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 12/13] nl80211: sanitize array index in parse_txq_params
  2018-01-30  1:02 ` Dan Williams
                   ` (11 preceding siblings ...)
  (?)
@ 2018-01-30  1:03 ` Dan Williams
  2018-01-30 22:38   ` [tip:x86/pti] nl80211: Sanitize " tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:03 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, Christian Lamparter, gregkh, kernel-hardening,
	linux-wireless, linux-kernel, Johannes Berg, torvalds,
	David S. Miller, Elena Reshetova, alan

Wireless drivers rely on parse_txq_params to validate that
txq_params->ac is less than NL80211_NUM_ACS by the time the low-level
driver's ->conf_tx() handler is called. Use a new helper,
array_index_nospec(), to sanitize txq_params->ac with respect to
speculation. I.e. ensure that any speculation into ->conf_tx() handlers
is done with a value of txq_params->ac that is within the bounds of [0,
NL80211_NUM_ACS).

Reported-by: Christian Lamparter <chunkeey@gmail.com>
Reported-by: Elena Reshetova <elena.reshetova@intel.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: linux-wireless@vger.kernel.org
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 net/wireless/nl80211.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d396cb61a280..81bef0676e1d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16,6 +16,7 @@
 #include <linux/nl80211.h>
 #include <linux/rtnetlink.h>
 #include <linux/netlink.h>
+#include <linux/nospec.h>
 #include <linux/etherdevice.h>
 #include <net/net_namespace.h>
 #include <net/genetlink.h>
@@ -2056,20 +2057,22 @@ static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
 static int parse_txq_params(struct nlattr *tb[],
 			    struct ieee80211_txq_params *txq_params)
 {
+	u8 ac;
+
 	if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
 	    !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
 	    !tb[NL80211_TXQ_ATTR_AIFS])
 		return -EINVAL;
 
-	txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
+	ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
 	txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
 	txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
 	txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
 	txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
 
-	if (txq_params->ac >= NL80211_NUM_ACS)
+	if (ac >= NL80211_NUM_ACS)
 		return -EINVAL;
-
+	txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
 	return 0;
 }
 

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v6 13/13] x86/spectre: report get_user mitigation for spectre_v1
  2018-01-30  1:02 ` Dan Williams
                   ` (12 preceding siblings ...)
  (?)
@ 2018-01-30  1:03 ` Dan Williams
  2018-01-30 22:38   ` [tip:x86/pti] x86/spectre: Report " tip-bot for Dan Williams
  -1 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-30  1:03 UTC (permalink / raw)
  To: tglx, mingo
  Cc: linux-arch, kernel-hardening, gregkh, x86, linux-kernel,
	torvalds, Ingo Molnar, H. Peter Anvin, Jiri Slaby, alan

Reflect the presence of get_user(), __get_user(), and 'syscall'
protections in sysfs. The expectation is that new and better tooling
will allow the kernel to grow more usages of array_index_nospec(), for
now, only claim mitigation for __user pointer de-references.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reported-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/kernel/cpu/bugs.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 390b3dc3d438..06f1d4c5ec6b 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -269,7 +269,7 @@ ssize_t cpu_show_spectre_v1(struct device *dev,
 {
 	if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V1))
 		return sprintf(buf, "Not affected\n");
-	return sprintf(buf, "Vulnerable\n");
+	return sprintf(buf, "Mitigation: __user pointer sanitization\n");
 }
 
 ssize_t cpu_show_spectre_v2(struct device *dev,

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] Documentation: Document array_index_nospec
  2018-01-30  1:02 ` [PATCH v6 01/13] Documentation: document array_index_nospec Dan Williams
@ 2018-01-30 22:33   ` tip-bot for Mark Rutland
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Mark Rutland @ 2018-01-30 22:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, peterz, corbet, tglx, keescook, dan.j.williams,
	will.deacon, mark.rutland, hpa, linux-kernel

Commit-ID:  f84a56f73dddaeac1dba8045b007f742f61cd2da
Gitweb:     https://git.kernel.org/tip/f84a56f73dddaeac1dba8045b007f742f61cd2da
Author:     Mark Rutland <mark.rutland@arm.com>
AuthorDate: Mon, 29 Jan 2018 17:02:16 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:28 +0100

Documentation: Document array_index_nospec

Document the rationale and usage of the new array_index_nospec() helper.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Cc: linux-arch@vger.kernel.org
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: gregkh@linuxfoundation.org
Cc: kernel-hardening@lists.openwall.com
Cc: torvalds@linux-foundation.org
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727413645.33451.15878817161436755393.stgit@dwillia2-desk3.amr.corp.intel.com

---
 Documentation/speculation.txt | 90 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/Documentation/speculation.txt b/Documentation/speculation.txt
new file mode 100644
index 0000000..e9e6cba
--- /dev/null
+++ b/Documentation/speculation.txt
@@ -0,0 +1,90 @@
+This document explains potential effects of speculation, and how undesirable
+effects can be mitigated portably using common APIs.
+
+===========
+Speculation
+===========
+
+To improve performance and minimize average latencies, many contemporary CPUs
+employ speculative execution techniques such as branch prediction, performing
+work which may be discarded at a later stage.
+
+Typically speculative execution cannot be observed from architectural state,
+such as the contents of registers. However, in some cases it is possible to
+observe its impact on microarchitectural state, such as the presence or
+absence of data in caches. Such state may form side-channels which can be
+observed to extract secret information.
+
+For example, in the presence of branch prediction, it is possible for bounds
+checks to be ignored by code which is speculatively executed. Consider the
+following code:
+
+	int load_array(int *array, unsigned int index)
+	{
+		if (index >= MAX_ARRAY_ELEMS)
+			return 0;
+		else
+			return array[index];
+	}
+
+Which, on arm64, may be compiled to an assembly sequence such as:
+
+	CMP	<index>, #MAX_ARRAY_ELEMS
+	B.LT	less
+	MOV	<returnval>, #0
+	RET
+  less:
+	LDR	<returnval>, [<array>, <index>]
+	RET
+
+It is possible that a CPU mis-predicts the conditional branch, and
+speculatively loads array[index], even if index >= MAX_ARRAY_ELEMS. This
+value will subsequently be discarded, but the speculated load may affect
+microarchitectural state which can be subsequently measured.
+
+More complex sequences involving multiple dependent memory accesses may
+result in sensitive information being leaked. Consider the following
+code, building on the prior example:
+
+	int load_dependent_arrays(int *arr1, int *arr2, int index)
+	{
+		int val1, val2,
+
+		val1 = load_array(arr1, index);
+		val2 = load_array(arr2, val1);
+
+		return val2;
+	}
+
+Under speculation, the first call to load_array() may return the value
+of an out-of-bounds address, while the second call will influence
+microarchitectural state dependent on this value. This may provide an
+arbitrary read primitive.
+
+====================================
+Mitigating speculation side-channels
+====================================
+
+The kernel provides a generic API to ensure that bounds checks are
+respected even under speculation. Architectures which are affected by
+speculation-based side-channels are expected to implement these
+primitives.
+
+The array_index_nospec() helper in <linux/nospec.h> can be used to
+prevent information from being leaked via side-channels.
+
+A call to array_index_nospec(index, size) returns a sanitized index
+value that is bounded to [0, size) even under cpu speculation
+conditions.
+
+This can be used to protect the earlier load_array() example:
+
+	int load_array(int *array, unsigned int index)
+	{
+		if (index >= MAX_ARRAY_ELEMS)
+			return 0;
+		else {
+			index = array_index_nospec(index, MAX_ARRAY_ELEMS);
+			return array[index];
+		}
+	}

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] array_index_nospec: Sanitize speculative array de-references
  2018-01-30  1:02 ` [PATCH v6 02/13] array_index_nospec: sanitize speculative array de-references Dan Williams
@ 2018-01-30 22:34   ` tip-bot for Dan Williams
  2018-02-16  8:55   ` [PATCH v6 02/13] array_index_nospec: sanitize " Christian Borntraeger
  1 sibling, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:34 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dan.j.williams, will.deacon, tglx, linux, cnovikov, mingo, ast,
	catalin.marinas, peterz, torvalds, hpa, linux-kernel

Commit-ID:  f3804203306e098dae9ca51540fcd5eb700d7f40
Gitweb:     https://git.kernel.org/tip/f3804203306e098dae9ca51540fcd5eb700d7f40
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:02:22 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:29 +0100

array_index_nospec: Sanitize speculative array de-references

array_index_nospec() is proposed as a generic mechanism to mitigate
against Spectre-variant-1 attacks, i.e. an attack that bypasses boundary
checks via speculative execution. The array_index_nospec()
implementation is expected to be safe for current generation CPUs across
multiple architectures (ARM, x86).

Based on an original implementation by Linus Torvalds, tweaked to remove
speculative flows by Alexei Starovoitov, and tweaked again by Linus to
introduce an x86 assembly implementation for the mask generation.

Co-developed-by: Linus Torvalds <torvalds@linux-foundation.org>
Co-developed-by: Alexei Starovoitov <ast@kernel.org>
Suggested-by: Cyril Novikov <cnovikov@lynx.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: kernel-hardening@lists.openwall.com
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: gregkh@linuxfoundation.org
Cc: torvalds@linux-foundation.org
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727414229.33451.18411580953862676575.stgit@dwillia2-desk3.amr.corp.intel.com

---
 include/linux/nospec.h | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/include/linux/nospec.h b/include/linux/nospec.h
new file mode 100644
index 0000000..b99bced
--- /dev/null
+++ b/include/linux/nospec.h
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright(c) 2018 Linus Torvalds. All rights reserved.
+// Copyright(c) 2018 Alexei Starovoitov. All rights reserved.
+// Copyright(c) 2018 Intel Corporation. All rights reserved.
+
+#ifndef _LINUX_NOSPEC_H
+#define _LINUX_NOSPEC_H
+
+/**
+ * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
+ * @index: array element index
+ * @size: number of elements in array
+ *
+ * When @index is out of bounds (@index >= @size), the sign bit will be
+ * set.  Extend the sign bit to all bits and invert, giving a result of
+ * zero for an out of bounds index, or ~0 if within bounds [0, @size).
+ */
+#ifndef array_index_mask_nospec
+static inline unsigned long array_index_mask_nospec(unsigned long index,
+						    unsigned long size)
+{
+	/*
+	 * Warn developers about inappropriate array_index_nospec() usage.
+	 *
+	 * Even if the CPU speculates past the WARN_ONCE branch, the
+	 * sign bit of @index is taken into account when generating the
+	 * mask.
+	 *
+	 * This warning is compiled out when the compiler can infer that
+	 * @index and @size are less than LONG_MAX.
+	 */
+	if (WARN_ONCE(index > LONG_MAX || size > LONG_MAX,
+			"array_index_nospec() limited to range of [0, LONG_MAX]\n"))
+		return 0;
+
+	/*
+	 * Always calculate and emit the mask even if the compiler
+	 * thinks the mask is not needed. The compiler does not take
+	 * into account the value of @index under speculation.
+	 */
+	OPTIMIZER_HIDE_VAR(index);
+	return ~(long)(index | (size - 1UL - index)) >> (BITS_PER_LONG - 1);
+}
+#endif
+
+/*
+ * array_index_nospec - sanitize an array index after a bounds check
+ *
+ * For a code sequence like:
+ *
+ *     if (index < size) {
+ *         index = array_index_nospec(index, size);
+ *         val = array[index];
+ *     }
+ *
+ * ...if the CPU speculates past the bounds check then
+ * array_index_nospec() will clamp the index within the range of [0,
+ * size).
+ */
+#define array_index_nospec(index, size)					\
+({									\
+	typeof(index) _i = (index);					\
+	typeof(size) _s = (size);					\
+	unsigned long _mask = array_index_mask_nospec(_i, _s);		\
+									\
+	BUILD_BUG_ON(sizeof(_i) > sizeof(long));			\
+	BUILD_BUG_ON(sizeof(_s) > sizeof(long));			\
+									\
+	_i &= _mask;							\
+	_i;								\
+})
+#endif /* _LINUX_NOSPEC_H */

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] x86: Implement array_index_mask_nospec
  2018-01-30  1:02 ` [PATCH v6 03/13] x86: implement array_index_mask_nospec Dan Williams
@ 2018-01-30 22:34   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:34 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dan.j.williams, tglx, mingo, torvalds, hpa, linux-kernel

Commit-ID:  babdde2698d482b6c0de1eab4f697cf5856c5859
Gitweb:     https://git.kernel.org/tip/babdde2698d482b6c0de1eab4f697cf5856c5859
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:02:28 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:29 +0100

x86: Implement array_index_mask_nospec

array_index_nospec() uses a mask to sanitize user controllable array
indexes, i.e. generate a 0 mask if 'index' >= 'size', and a ~0 mask
otherwise. While the default array_index_mask_nospec() handles the
carry-bit from the (index - size) result in software.

The x86 array_index_mask_nospec() does the same, but the carry-bit is
handled in the processor CF flag without conditional instructions in the
control flow.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727414808.33451.1873237130672785331.stgit@dwillia2-desk3.amr.corp.intel.com

---
 arch/x86/include/asm/barrier.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
index 7fb3362..173b38f 100644
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -24,6 +24,30 @@
 #define wmb()	asm volatile("sfence" ::: "memory")
 #endif
 
+/**
+ * array_index_mask_nospec() - generate a mask that is ~0UL when the
+ * 	bounds check succeeds and 0 otherwise
+ * @index: array element index
+ * @size: number of elements in array
+ *
+ * Returns:
+ *     0 - (index < size)
+ */
+static inline unsigned long array_index_mask_nospec(unsigned long index,
+		unsigned long size)
+{
+	unsigned long mask;
+
+	asm ("cmp %1,%2; sbb %0,%0;"
+			:"=r" (mask)
+			:"r"(size),"r" (index)
+			:"cc");
+	return mask;
+}
+
+/* Override the default implementation from linux/nospec.h. */
+#define array_index_mask_nospec array_index_mask_nospec
+
 #ifdef CONFIG_X86_PPRO_FENCE
 #define dma_rmb()	rmb()
 #else

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] x86: Introduce barrier_nospec
  2018-01-30  1:02 ` [PATCH v6 04/13] x86: introduce barrier_nospec Dan Williams
@ 2018-01-30 22:35   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:35 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, torvalds, thomas.lendacky, keescook, dan.j.williams,
	mingo, viro, linux-kernel, hpa, tglx, ak

Commit-ID:  b3d7ad85b80bbc404635dca80f5b129f6242bc7a
Gitweb:     https://git.kernel.org/tip/b3d7ad85b80bbc404635dca80f5b129f6242bc7a
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:02:33 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:29 +0100

x86: Introduce barrier_nospec

Rename the open coded form of this instruction sequence from
rdtsc_ordered() into a generic barrier primitive, barrier_nospec().

One of the mitigations for Spectre variant1 vulnerabilities is to fence
speculative execution after successfully validating a bounds check. I.e.
force the result of a bounds check to resolve in the instruction pipeline
to ensure speculative execution honors that result before potentially
operating on out-of-bounds data.

No functional changes.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Suggested-by: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727415361.33451.9049453007262764675.stgit@dwillia2-desk3.amr.corp.intel.com

---
 arch/x86/include/asm/barrier.h | 4 ++++
 arch/x86/include/asm/msr.h     | 3 +--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
index 173b38f..30d4061 100644
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -48,6 +48,10 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
 /* Override the default implementation from linux/nospec.h. */
 #define array_index_mask_nospec array_index_mask_nospec
 
+/* Prevent speculative execution past this barrier. */
+#define barrier_nospec() alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC, \
+					   "lfence", X86_FEATURE_LFENCE_RDTSC)
+
 #ifdef CONFIG_X86_PPRO_FENCE
 #define dma_rmb()	rmb()
 #else
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 07962f5..30df295 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -214,8 +214,7 @@ static __always_inline unsigned long long rdtsc_ordered(void)
 	 * that some other imaginary CPU is updating continuously with a
 	 * time stamp.
 	 */
-	alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC,
-			  "lfence", X86_FEATURE_LFENCE_RDTSC);
+	barrier_nospec();
 	return rdtsc();
 }
 

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] x86: Introduce __uaccess_begin_nospec() and uaccess_try_nospec
  2018-01-30  1:02 ` [PATCH v6 05/13] x86: introduce __uaccess_begin_nospec Dan Williams
@ 2018-01-30 22:35   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:35 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: thomas.lendacky, dan.j.williams, viro, torvalds, keescook, hpa,
	linux-kernel, tglx, ak, mingo, mingo

Commit-ID:  b3bbfb3fb5d25776b8e3f361d2eedaabb0b496cd
Gitweb:     https://git.kernel.org/tip/b3bbfb3fb5d25776b8e3f361d2eedaabb0b496cd
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:02:39 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:30 +0100

x86: Introduce __uaccess_begin_nospec() and uaccess_try_nospec

For __get_user() paths, do not allow the kernel to speculate on the value
of a user controlled pointer. In addition to the 'stac' instruction for
Supervisor Mode Access Protection (SMAP), a barrier_nospec() causes the
access_ok() result to resolve in the pipeline before the CPU might take any
speculative action on the pointer value. Given the cost of 'stac' the
speculation barrier is placed after 'stac' to hopefully overlap the cost of
disabling SMAP with the cost of flushing the instruction pipeline.

Since __get_user is a major kernel interface that deals with user
controlled pointers, the __uaccess_begin_nospec() mechanism will prevent
speculative execution past an access_ok() permission check. While
speculative execution past access_ok() is not enough to lead to a kernel
memory leak, it is a necessary precondition.

To be clear, __uaccess_begin_nospec() is addressing a class of potential
problems near __get_user() usages.

Note, that while the barrier_nospec() in __uaccess_begin_nospec() is used
to protect __get_user(), pointer masking similar to array_index_nospec()
will be used for get_user() since it incorporates a bounds check near the
usage.

uaccess_try_nospec provides the same mechanism for get_user_try.

No functional changes.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Suggested-by: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727415922.33451.5796614273104346583.stgit@dwillia2-desk3.amr.corp.intel.com

---
 arch/x86/include/asm/uaccess.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 574dff4..663e9bd 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -124,6 +124,11 @@ extern int __get_user_bad(void);
 
 #define __uaccess_begin() stac()
 #define __uaccess_end()   clac()
+#define __uaccess_begin_nospec()	\
+({					\
+	stac();				\
+	barrier_nospec();		\
+})
 
 /*
  * This is a type: either unsigned long, if the argument fits into
@@ -487,6 +492,10 @@ struct __large_struct { unsigned long buf[100]; };
 	__uaccess_begin();						\
 	barrier();
 
+#define uaccess_try_nospec do {						\
+	current->thread.uaccess_err = 0;				\
+	__uaccess_begin_nospec();					\
+
 #define uaccess_catch(err)						\
 	__uaccess_end();						\
 	(err) |= (current->thread.uaccess_err ? -EFAULT : 0);		\

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] x86/usercopy: Replace open coded stac/clac with __uaccess_{begin, end}
  2018-01-30  1:02 ` [PATCH v6 06/13] x86, usercopy: replace open coded stac/clac with __uaccess_{begin, end} Dan Williams
@ 2018-01-30 22:35   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:35 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, tglx, dan.j.williams, viro, keescook, mingo, mingo,
	hpa, thomas.lendacky

Commit-ID:  b5c4ae4f35325d520b230bab6eb3310613b72ac1
Gitweb:     https://git.kernel.org/tip/b5c4ae4f35325d520b230bab6eb3310613b72ac1
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:02:44 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:30 +0100

x86/usercopy: Replace open coded stac/clac with __uaccess_{begin, end}

In preparation for converting some __uaccess_begin() instances to
__uacess_begin_nospec(), make sure all 'from user' uaccess paths are
using the _begin(), _end() helpers rather than open-coded stac() and
clac().

No functional changes.

Suggested-by: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: torvalds@linux-foundation.org
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727416438.33451.17309465232057176966.stgit@dwillia2-desk3.amr.corp.intel.com

---
 arch/x86/lib/usercopy_32.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 1b377f7..de34367 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -331,12 +331,12 @@ do {									\
 
 unsigned long __copy_user_ll(void *to, const void *from, unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
 		n = __copy_user_intel(to, from, n);
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_user_ll);
@@ -344,7 +344,7 @@ EXPORT_SYMBOL(__copy_user_ll);
 unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
 					unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
 		n = __copy_user_intel_nocache(to, from, n);
@@ -353,7 +353,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
 #else
 	__copy_user(to, from, n);
 #endif
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec
  2018-01-30  1:02 ` [PATCH v6 07/13] x86, __get_user: use __uaccess_begin_nospec Dan Williams
@ 2018-01-30 22:36   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:36 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, dan.j.williams, torvalds, tglx, keescook, viro,
	mingo, ak, hpa

Commit-ID:  304ec1b050310548db33063e567123fae8fd0301
Gitweb:     https://git.kernel.org/tip/304ec1b050310548db33063e567123fae8fd0301
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:02:49 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:31 +0100

x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec

Quoting Linus:

    I do think that it would be a good idea to very expressly document
    the fact that it's not that the user access itself is unsafe. I do
    agree that things like "get_user()" want to be protected, but not
    because of any direct bugs or problems with get_user() and friends,
    but simply because get_user() is an excellent source of a pointer
    that is obviously controlled from a potentially attacking user
    space. So it's a prime candidate for then finding _subsequent_
    accesses that can then be used to perturb the cache.

__uaccess_begin_nospec() covers __get_user() and copy_from_iter() where the
limit check is far away from the user pointer de-reference. In those cases
a barrier_nospec() prevents speculation with a potential pointer to
privileged memory. uaccess_try_nospec covers get_user_try.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727416953.33451.10508284228526170604.stgit@dwillia2-desk3.amr.corp.intel.com

---
 arch/x86/include/asm/uaccess.h    |  6 +++---
 arch/x86/include/asm/uaccess_32.h |  6 +++---
 arch/x86/include/asm/uaccess_64.h | 12 ++++++------
 arch/x86/lib/usercopy_32.c        |  4 ++--
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 663e9bd..aae77eb 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -450,7 +450,7 @@ do {									\
 ({									\
 	int __gu_err;							\
 	__inttype(*(ptr)) __gu_val;					\
-	__uaccess_begin();						\
+	__uaccess_begin_nospec();					\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);	\
 	__uaccess_end();						\
 	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
@@ -557,7 +557,7 @@ struct __large_struct { unsigned long buf[100]; };
  *	get_user_ex(...);
  * } get_user_catch(err)
  */
-#define get_user_try		uaccess_try
+#define get_user_try		uaccess_try_nospec
 #define get_user_catch(err)	uaccess_catch(err)
 
 #define get_user_ex(x, ptr)	do {					\
@@ -591,7 +591,7 @@ extern void __cmpxchg_wrong_size(void)
 	__typeof__(ptr) __uval = (uval);				\
 	__typeof__(*(ptr)) __old = (old);				\
 	__typeof__(*(ptr)) __new = (new);				\
-	__uaccess_begin();						\
+	__uaccess_begin_nospec();					\
 	switch (size) {							\
 	case 1:								\
 	{								\
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 7295040..ba2dc19 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -29,21 +29,21 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long n)
 		switch (n) {
 		case 1:
 			ret = 0;
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_asm_nozero(*(u8 *)to, from, ret,
 					      "b", "b", "=q", 1);
 			__uaccess_end();
 			return ret;
 		case 2:
 			ret = 0;
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_asm_nozero(*(u16 *)to, from, ret,
 					      "w", "w", "=r", 2);
 			__uaccess_end();
 			return ret;
 		case 4:
 			ret = 0;
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_asm_nozero(*(u32 *)to, from, ret,
 					      "l", "k", "=r", 4);
 			__uaccess_end();
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index f07ef3c..62546b3 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -55,31 +55,31 @@ raw_copy_from_user(void *dst, const void __user *src, unsigned long size)
 		return copy_user_generic(dst, (__force void *)src, size);
 	switch (size) {
 	case 1:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u8 *)dst, (u8 __user *)src,
 			      ret, "b", "b", "=q", 1);
 		__uaccess_end();
 		return ret;
 	case 2:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u16 *)dst, (u16 __user *)src,
 			      ret, "w", "w", "=r", 2);
 		__uaccess_end();
 		return ret;
 	case 4:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u32 *)dst, (u32 __user *)src,
 			      ret, "l", "k", "=r", 4);
 		__uaccess_end();
 		return ret;
 	case 8:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
 			      ret, "q", "", "=r", 8);
 		__uaccess_end();
 		return ret;
 	case 10:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
 			       ret, "q", "", "=r", 10);
 		if (likely(!ret))
@@ -89,7 +89,7 @@ raw_copy_from_user(void *dst, const void __user *src, unsigned long size)
 		__uaccess_end();
 		return ret;
 	case 16:
-		__uaccess_begin();
+		__uaccess_begin_nospec();
 		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
 			       ret, "q", "", "=r", 16);
 		if (likely(!ret))
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index de34367..7add8ba 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -331,7 +331,7 @@ do {									\
 
 unsigned long __copy_user_ll(void *to, const void *from, unsigned long n)
 {
-	__uaccess_begin();
+	__uaccess_begin_nospec();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
@@ -344,7 +344,7 @@ EXPORT_SYMBOL(__copy_user_ll);
 unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
 					unsigned long n)
 {
-	__uaccess_begin();
+	__uaccess_begin_nospec();
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
 		n = __copy_user_intel_nocache(to, from, n);

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] x86/get_user: Use pointer masking to limit speculation
  2018-01-30  1:02 ` [PATCH v6 08/13] x86, get_user: use pointer masking to limit speculation Dan Williams
@ 2018-01-30 22:36   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:36 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dan.j.williams, linux-kernel, torvalds, viro, luto, tglx, hpa,
	mingo, keescook

Commit-ID:  c7f631cb07e7da06ac1d231ca178452339e32a94
Gitweb:     https://git.kernel.org/tip/c7f631cb07e7da06ac1d231ca178452339e32a94
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:02:54 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:31 +0100

x86/get_user: Use pointer masking to limit speculation

Quoting Linus:

    I do think that it would be a good idea to very expressly document
    the fact that it's not that the user access itself is unsafe. I do
    agree that things like "get_user()" want to be protected, but not
    because of any direct bugs or problems with get_user() and friends,
    but simply because get_user() is an excellent source of a pointer
    that is obviously controlled from a potentially attacking user
    space. So it's a prime candidate for then finding _subsequent_
    accesses that can then be used to perturb the cache.

Unlike the __get_user() case get_user() includes the address limit check
near the pointer de-reference. With that locality the speculation can be
mitigated with pointer narrowing rather than a barrier, i.e.
array_index_nospec(). Where the narrowing is performed by:

	cmp %limit, %ptr
	sbb %mask, %mask
	and %mask, %ptr

With respect to speculation the value of %ptr is either less than %limit
or NULL.

Co-developed-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: torvalds@linux-foundation.org
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727417469.33451.11804043010080838495.stgit@dwillia2-desk3.amr.corp.intel.com

---
 arch/x86/lib/getuser.S | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index c97d935..49b167f 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -40,6 +40,8 @@ ENTRY(__get_user_1)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 1:	movzbl (%_ASM_AX),%edx
 	xor %eax,%eax
@@ -54,6 +56,8 @@ ENTRY(__get_user_2)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 2:	movzwl -1(%_ASM_AX),%edx
 	xor %eax,%eax
@@ -68,6 +72,8 @@ ENTRY(__get_user_4)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 3:	movl -3(%_ASM_AX),%edx
 	xor %eax,%eax
@@ -83,6 +89,8 @@ ENTRY(__get_user_8)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 4:	movq -7(%_ASM_AX),%rdx
 	xor %eax,%eax
@@ -94,6 +102,8 @@ ENTRY(__get_user_8)
 	mov PER_CPU_VAR(current_task), %_ASM_DX
 	cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user_8
+	sbb %_ASM_DX, %_ASM_DX		/* array_index_mask_nospec() */
+	and %_ASM_DX, %_ASM_AX
 	ASM_STAC
 4:	movl -7(%_ASM_AX),%edx
 5:	movl -3(%_ASM_AX),%ecx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] x86/syscall: Sanitize syscall table de-references under speculation
  2018-01-30  1:02 ` [PATCH v6 09/13] x86: sanitize syscall table de-references under speculation Dan Williams
@ 2018-01-30 22:37   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: luto, torvalds, tglx, linux-kernel, hpa, dan.j.williams, mingo

Commit-ID:  2fbd7af5af8665d18bcefae3e9700be07e22b681
Gitweb:     https://git.kernel.org/tip/2fbd7af5af8665d18bcefae3e9700be07e22b681
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:02:59 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:31 +0100

x86/syscall: Sanitize syscall table de-references under speculation

The syscall table base is a user controlled function pointer in kernel
space. Use array_index_nospec() to prevent any out of bounds speculation.

While retpoline prevents speculating into a userspace directed target it
does not stop the pointer de-reference, the concern is leaking memory
relative to the syscall table base, by observing instruction cache
behavior.

Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Andy Lutomirski <luto@kernel.org>
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727417984.33451.1216731042505722161.stgit@dwillia2-desk3.amr.corp.intel.com

---
 arch/x86/entry/common.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 9908134..21dbdf0 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -21,6 +21,7 @@
 #include <linux/export.h>
 #include <linux/context_tracking.h>
 #include <linux/user-return-notifier.h>
+#include <linux/nospec.h>
 #include <linux/uprobes.h>
 #include <linux/livepatch.h>
 #include <linux/syscalls.h>
@@ -282,7 +283,8 @@ __visible void do_syscall_64(struct pt_regs *regs)
 	 * regs->orig_ax, which changes the behavior of some syscalls.
 	 */
 	if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) {
-		regs->ax = sys_call_table[nr & __SYSCALL_MASK](
+		nr = array_index_nospec(nr & __SYSCALL_MASK, NR_syscalls);
+		regs->ax = sys_call_table[nr](
 			regs->di, regs->si, regs->dx,
 			regs->r10, regs->r8, regs->r9);
 	}
@@ -318,6 +320,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
 	}
 
 	if (likely(nr < IA32_NR_syscalls)) {
+		nr = array_index_nospec(nr, IA32_NR_syscalls);
 		/*
 		 * It's possible that a 32-bit syscall implementation
 		 * takes a 64-bit parameter but nonetheless assumes that

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] vfs, fdtable: Prevent bounds-check bypass via speculative execution
  2018-01-30  1:03 ` [PATCH v6 10/13] vfs, fdtable: prevent bounds-check bypass via speculative execution Dan Williams
@ 2018-01-30 22:37   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, viro, dan.j.williams, hpa, mingo, linux-kernel, elena.reshetova

Commit-ID:  56c30ba7b348b90484969054d561f711ba196507
Gitweb:     https://git.kernel.org/tip/56c30ba7b348b90484969054d561f711ba196507
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:03:05 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:32 +0100

vfs, fdtable: Prevent bounds-check bypass via speculative execution

'fd' is a user controlled value that is used as a data dependency to
read from the 'fdt->fd' array.  In order to avoid potential leaks of
kernel memory values, block speculative execution of the instruction
stream that could issue reads based on an invalid 'file *' returned from
__fcheck_files.

Co-developed-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: torvalds@linux-foundation.org
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727418500.33451.17392199002892248656.stgit@dwillia2-desk3.amr.corp.intel.com

---
 include/linux/fdtable.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 1c65817..41615f3 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -10,6 +10,7 @@
 #include <linux/compiler.h>
 #include <linux/spinlock.h>
 #include <linux/rcupdate.h>
+#include <linux/nospec.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/fs.h>
@@ -82,8 +83,10 @@ static inline struct file *__fcheck_files(struct files_struct *files, unsigned i
 {
 	struct fdtable *fdt = rcu_dereference_raw(files->fdt);
 
-	if (fd < fdt->max_fds)
+	if (fd < fdt->max_fds) {
+		fd = array_index_nospec(fd, fdt->max_fds);
 		return rcu_dereference_raw(fdt->fd[fd]);
+	}
 	return NULL;
 }
 

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] nl80211: Sanitize array index in parse_txq_params
  2018-01-30  1:03 ` [PATCH v6 12/13] nl80211: sanitize array index in parse_txq_params Dan Williams
@ 2018-01-30 22:38   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: chunkeey, johannes, tglx, davem, mingo, elena.reshetova, hpa,
	dan.j.williams, linux-kernel

Commit-ID:  259d8c1e984318497c84eef547bbb6b1d9f4eb05
Gitweb:     https://git.kernel.org/tip/259d8c1e984318497c84eef547bbb6b1d9f4eb05
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:03:15 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:32 +0100

nl80211: Sanitize array index in parse_txq_params

Wireless drivers rely on parse_txq_params to validate that txq_params->ac
is less than NL80211_NUM_ACS by the time the low-level driver's ->conf_tx()
handler is called. Use a new helper, array_index_nospec(), to sanitize
txq_params->ac with respect to speculation. I.e. ensure that any
speculation into ->conf_tx() handlers is done with a value of
txq_params->ac that is within the bounds of [0, NL80211_NUM_ACS).

Reported-by: Christian Lamparter <chunkeey@gmail.com>
Reported-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Cc: linux-arch@vger.kernel.org
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: linux-wireless@vger.kernel.org
Cc: torvalds@linux-foundation.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727419584.33451.7700736761686184303.stgit@dwillia2-desk3.amr.corp.intel.com

---
 net/wireless/nl80211.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 542a4fc..4bbcfc1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16,6 +16,7 @@
 #include <linux/nl80211.h>
 #include <linux/rtnetlink.h>
 #include <linux/netlink.h>
+#include <linux/nospec.h>
 #include <linux/etherdevice.h>
 #include <net/net_namespace.h>
 #include <net/genetlink.h>
@@ -2056,20 +2057,22 @@ static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {
 static int parse_txq_params(struct nlattr *tb[],
 			    struct ieee80211_txq_params *txq_params)
 {
+	u8 ac;
+
 	if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||
 	    !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||
 	    !tb[NL80211_TXQ_ATTR_AIFS])
 		return -EINVAL;
 
-	txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
+	ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);
 	txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);
 	txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);
 	txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);
 	txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]);
 
-	if (txq_params->ac >= NL80211_NUM_ACS)
+	if (ac >= NL80211_NUM_ACS)
 		return -EINVAL;
-
+	txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);
 	return 0;
 }
 

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [tip:x86/pti] x86/spectre: Report get_user mitigation for spectre_v1
  2018-01-30  1:03 ` [PATCH v6 13/13] x86/spectre: report get_user mitigation for spectre_v1 Dan Williams
@ 2018-01-30 22:38   ` tip-bot for Dan Williams
  0 siblings, 0 replies; 32+ messages in thread
From: tip-bot for Dan Williams @ 2018-01-30 22:38 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: jslaby, dan.j.williams, mingo, hpa, linux-kernel, tglx

Commit-ID:  edfbae53dab8348fca778531be9f4855d2ca0360
Gitweb:     https://git.kernel.org/tip/edfbae53dab8348fca778531be9f4855d2ca0360
Author:     Dan Williams <dan.j.williams@intel.com>
AuthorDate: Mon, 29 Jan 2018 17:03:21 -0800
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 30 Jan 2018 21:54:32 +0100

x86/spectre: Report get_user mitigation for spectre_v1

Reflect the presence of get_user(), __get_user(), and 'syscall' protections
in sysfs. The expectation is that new and better tooling will allow the
kernel to grow more usages of array_index_nospec(), for now, only claim
mitigation for __user pointer de-references.

Reported-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: torvalds@linux-foundation.org
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727420158.33451.11658324346540434635.stgit@dwillia2-desk3.amr.corp.intel.com

---
 arch/x86/kernel/cpu/bugs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 400c34e..fdb6068 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -297,7 +297,7 @@ ssize_t cpu_show_spectre_v1(struct device *dev,
 {
 	if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V1))
 		return sprintf(buf, "Not affected\n");
-	return sprintf(buf, "Vulnerable\n");
+	return sprintf(buf, "Mitigation: __user pointer sanitization\n");
 }
 
 ssize_t cpu_show_spectre_v2(struct device *dev,

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH v6 11/13] kvm, x86: update spectre-v1 mitigation
  2018-01-30  1:03 ` [PATCH v6 11/13] kvm, x86: update spectre-v1 mitigation Dan Williams
@ 2018-01-31  3:22   ` Dan Williams
  2018-01-31  8:07     ` Thomas Gleixner
  0 siblings, 1 reply; 32+ messages in thread
From: Dan Williams @ 2018-01-31  3:22 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar
  Cc: linux-arch, Kernel Hardening, Andrew Honig,
	Linux Kernel Mailing List, Greg KH, Paolo Bonzini, Alan Cox,
	Linus Torvalds, Jim Mattson

On Mon, Jan 29, 2018 at 5:03 PM, Dan Williams <dan.j.williams@intel.com> wrote:
> Commit 75f139aaf896 "KVM: x86: Add memory barrier on vmcs field lookup"
> added a raw 'asm("lfence");' to prevent a bounds check bypass of
> 'vmcs_field_to_offset_table'. We can save an lfence in this path and
> just use the common array_index_nospec() helper designed for these types
> of fixes.
>
> Cc: Andrew Honig <ahonig@google.com>
> Cc: Jim Mattson <jmattson@google.com>
> Acked-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>


Hi Thomas,

I notice this one missing from -tip, I suspect because of the
collision with the raw 'lfence' that is in current mainline? No
worries, I'll send a rebased fixup to Paolo directly once
array_idx_nospec() goes upstream.


> ---
>  arch/x86/kvm/vmx.c |   14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 924589c53422..8514186241d2 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -34,6 +34,7 @@
>  #include <linux/tboot.h>
>  #include <linux/hrtimer.h>
>  #include <linux/frame.h>
> +#include <linux/nospec.h>
>  #include "kvm_cache_regs.h"
>  #include "x86.h"
>
> @@ -883,13 +884,18 @@ static const unsigned short vmcs_field_to_offset_table[] = {
>
>  static inline short vmcs_field_to_offset(unsigned long field)
>  {
> -       BUILD_BUG_ON(ARRAY_SIZE(vmcs_field_to_offset_table) > SHRT_MAX);
> +       const size_t size = ARRAY_SIZE(vmcs_field_to_offset_table);
> +       unsigned short offset;
>
> -       if (field >= ARRAY_SIZE(vmcs_field_to_offset_table) ||
> -           vmcs_field_to_offset_table[field] == 0)
> +       BUILD_BUG_ON(size > SHRT_MAX);
> +       if (field >= size)
>                 return -ENOENT;
>
> -       return vmcs_field_to_offset_table[field];
> +       field = array_index_nospec(field, size);
> +       offset = vmcs_field_to_offset_table[field];
> +       if (offset == 0)
> +               return -ENOENT;
> +       return offset;
>  }
>
>  static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v6 11/13] kvm, x86: update spectre-v1 mitigation
  2018-01-31  3:22   ` Dan Williams
@ 2018-01-31  8:07     ` Thomas Gleixner
  2018-01-31 13:49       ` Paolo Bonzini
  0 siblings, 1 reply; 32+ messages in thread
From: Thomas Gleixner @ 2018-01-31  8:07 UTC (permalink / raw)
  To: Dan Williams
  Cc: Ingo Molnar, linux-arch, Kernel Hardening, Andrew Honig,
	Linux Kernel Mailing List, Greg KH, Paolo Bonzini, Alan Cox,
	Linus Torvalds, Jim Mattson

On Tue, 30 Jan 2018, Dan Williams wrote:

> On Mon, Jan 29, 2018 at 5:03 PM, Dan Williams <dan.j.williams@intel.com> wrote:
> > Commit 75f139aaf896 "KVM: x86: Add memory barrier on vmcs field lookup"
> > added a raw 'asm("lfence");' to prevent a bounds check bypass of
> > 'vmcs_field_to_offset_table'. We can save an lfence in this path and
> > just use the common array_index_nospec() helper designed for these types
> > of fixes.
> >
> > Cc: Andrew Honig <ahonig@google.com>
> > Cc: Jim Mattson <jmattson@google.com>
> > Acked-by: Paolo Bonzini <pbonzini@redhat.com>
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> 
> 
> Hi Thomas,
> 
> I notice this one missing from -tip, I suspect because of the
> collision with the raw 'lfence' that is in current mainline? No
> worries, I'll send a rebased fixup to Paolo directly once
> array_idx_nospec() goes upstream.

It did not apply for that reason and I'm still trying to keep x86/pti as
clean as it goes to keep GregKHs backporting hell somehow under control.

Sorry, I wanted to reply on that, but then my brain shut down after pushing
it out.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v6 11/13] kvm, x86: update spectre-v1 mitigation
  2018-01-31  8:07     ` Thomas Gleixner
@ 2018-01-31 13:49       ` Paolo Bonzini
  2018-01-31 15:42         ` Thomas Gleixner
  0 siblings, 1 reply; 32+ messages in thread
From: Paolo Bonzini @ 2018-01-31 13:49 UTC (permalink / raw)
  To: Thomas Gleixner, Dan Williams
  Cc: Ingo Molnar, linux-arch, Kernel Hardening, Andrew Honig,
	Linux Kernel Mailing List, Greg KH, Alan Cox, Linus Torvalds,
	Jim Mattson

On 31/01/2018 03:07, Thomas Gleixner wrote:
>> Hi Thomas,
>>
>> I notice this one missing from -tip, I suspect because of the
>> collision with the raw 'lfence' that is in current mainline? No
>> worries, I'll send a rebased fixup to Paolo directly once
>> array_idx_nospec() goes upstream.

Fine by me.  Also, now that x86/pti has been rebased, a version that
replaces the lfence with array_idx_nospec() would apply to both tip and
4.14.

Paolo

> It did not apply for that reason and I'm still trying to keep x86/pti as
> clean as it goes to keep GregKHs backporting hell somehow under control.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v6 11/13] kvm, x86: update spectre-v1 mitigation
  2018-01-31 13:49       ` Paolo Bonzini
@ 2018-01-31 15:42         ` Thomas Gleixner
  0 siblings, 0 replies; 32+ messages in thread
From: Thomas Gleixner @ 2018-01-31 15:42 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Dan Williams, Ingo Molnar, linux-arch, Kernel Hardening,
	Andrew Honig, Linux Kernel Mailing List, Greg KH, Alan Cox,
	Linus Torvalds, Jim Mattson

On Wed, 31 Jan 2018, Paolo Bonzini wrote:

> On 31/01/2018 03:07, Thomas Gleixner wrote:
> >> Hi Thomas,
> >>
> >> I notice this one missing from -tip, I suspect because of the
> >> collision with the raw 'lfence' that is in current mainline? No
> >> worries, I'll send a rebased fixup to Paolo directly once
> >> array_idx_nospec() goes upstream.
> 
> Fine by me.  Also, now that x86/pti has been rebased, a version that
> replaces the lfence with array_idx_nospec() would apply to both tip and
> 4.14.

I'm happy to take it.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v6 02/13] array_index_nospec: sanitize speculative array de-references
  2018-01-30  1:02 ` [PATCH v6 02/13] array_index_nospec: sanitize speculative array de-references Dan Williams
  2018-01-30 22:34   ` [tip:x86/pti] array_index_nospec: Sanitize " tip-bot for Dan Williams
@ 2018-02-16  8:55   ` Christian Borntraeger
  1 sibling, 0 replies; 32+ messages in thread
From: Christian Borntraeger @ 2018-02-16  8:55 UTC (permalink / raw)
  To: Dan Williams, tglx, mingo
  Cc: linux-arch, Cyril Novikov, kernel-hardening, Peter Zijlstra,
	Catalin Marinas, x86, Will Deacon, Russell King, linux-kernel,
	Ingo Molnar, gregkh, H. Peter Anvin, torvalds, alan



On 01/30/2018 02:02 AM, Dan Williams wrote:
> array_index_nospec() is proposed as a generic mechanism to mitigate
> against Spectre-variant-1 attacks, i.e. an attack that bypasses boundary
> checks via speculative execution. The array_index_nospec()
> implementation is expected to be safe for current generation CPUs across
> multiple architectures (ARM, x86).
> 
> Based on an original implementation by Linus Torvalds, tweaked to remove
> speculative flows by Alexei Starovoitov, and tweaked again by Linus to
> introduce an x86 assembly implementation for the mask generation.
> 
> Co-developed-by: Linus Torvalds <torvalds@linux-foundation.org>
> Co-developed-by: Alexei Starovoitov <ast@kernel.org>
> Suggested-by: Cyril Novikov <cnovikov@lynx.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: x86@kernel.org
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  include/linux/nospec.h |   72 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 72 insertions(+)
>  create mode 100644 include/linux/nospec.h
> 
> diff --git a/include/linux/nospec.h b/include/linux/nospec.h
> new file mode 100644
> index 000000000000..cf7be4bbcf17
> --- /dev/null
> +++ b/include/linux/nospec.h
> @@ -0,0 +1,72 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright(c) 2018 Linus Torvalds. All rights reserved.
> +// Copyright(c) 2018 Alexei Starovoitov. All rights reserved.
> +// Copyright(c) 2018 Intel Corporation. All rights reserved.
> +
> +#ifndef _LINUX_NOSPEC_H
> +#define _LINUX_NOSPEC_H


Hmmm, shouldn't we include asm/barrier.h here? Otherwise users might or might not
use the optimized variant depending on which headers are included by the users
of array_index_nospec.


> +
> +/**
> + * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
> + * @index: array element index
> + * @size: number of elements in array
> + *
> + * When @index is out of bounds (@index >= @size), the sign bit will be
> + * set.  Extend the sign bit to all bits and invert, giving a result of
> + * zero for an out of bounds index, or ~0 if within bounds [0, @size).
> + */
> +#ifndef array_index_mask_nospec
> +static inline unsigned long array_index_mask_nospec(unsigned long index,
> +		unsigned long size)
> +{
> +	/*
> +	 * Warn developers about inappropriate array_index_nospec() usage.
> +	 *
> +	 * Even if the CPU speculates past the WARN_ONCE branch, the
> +	 * sign bit of @index is taken into account when generating the
> +	 * mask.
> +	 *
> +	 * This warning is compiled out when the compiler can infer that
> +	 * @index and @size are less than LONG_MAX.
> +	 */
> +	if (WARN_ONCE(index > LONG_MAX || size > LONG_MAX,
> +			"array_index_nospec() limited to range of [0, LONG_MAX]\n"))
> +		return 0;
> +
> +	/*
> +	 * Always calculate and emit the mask even if the compiler
> +	 * thinks the mask is not needed. The compiler does not take
> +	 * into account the value of @index under speculation.
> +	 */
> +	OPTIMIZER_HIDE_VAR(index);
> +	return ~(long)(index | (size - 1UL - index)) >> (BITS_PER_LONG - 1);
> +}
> +#endif
> +
> +/*
> + * array_index_nospec - sanitize an array index after a bounds check
> + *
> + * For a code sequence like:
> + *
> + *     if (index < size) {
> + *         index = array_index_nospec(index, size);
> + *         val = array[index];
> + *     }
> + *
> + * ...if the CPU speculates past the bounds check then
> + * array_index_nospec() will clamp the index within the range of [0,
> + * size).
> + */
> +#define array_index_nospec(index, size)					\
> +({									\
> +	typeof(index) _i = (index);					\
> +	typeof(size) _s = (size);					\
> +	unsigned long _mask = array_index_mask_nospec(_i, _s);		\
> +									\
> +	BUILD_BUG_ON(sizeof(_i) > sizeof(long));			\
> +	BUILD_BUG_ON(sizeof(_s) > sizeof(long));			\
> +									\
> +	_i &= _mask;							\
> +	_i;								\
> +})
> +#endif /* _LINUX_NOSPEC_H */
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2018-02-16  8:55 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-30  1:02 [PATCH v6 00/13] spectre variant1 mitigations for tip/x86/pti Dan Williams
2018-01-30  1:02 ` Dan Williams
2018-01-30  1:02 ` [PATCH v6 01/13] Documentation: document array_index_nospec Dan Williams
2018-01-30 22:33   ` [tip:x86/pti] Documentation: Document array_index_nospec tip-bot for Mark Rutland
2018-01-30  1:02 ` [PATCH v6 02/13] array_index_nospec: sanitize speculative array de-references Dan Williams
2018-01-30 22:34   ` [tip:x86/pti] array_index_nospec: Sanitize " tip-bot for Dan Williams
2018-02-16  8:55   ` [PATCH v6 02/13] array_index_nospec: sanitize " Christian Borntraeger
2018-01-30  1:02 ` [PATCH v6 03/13] x86: implement array_index_mask_nospec Dan Williams
2018-01-30 22:34   ` [tip:x86/pti] x86: Implement array_index_mask_nospec tip-bot for Dan Williams
2018-01-30  1:02 ` [PATCH v6 04/13] x86: introduce barrier_nospec Dan Williams
2018-01-30 22:35   ` [tip:x86/pti] x86: Introduce barrier_nospec tip-bot for Dan Williams
2018-01-30  1:02 ` [PATCH v6 05/13] x86: introduce __uaccess_begin_nospec Dan Williams
2018-01-30 22:35   ` [tip:x86/pti] x86: Introduce __uaccess_begin_nospec() and uaccess_try_nospec tip-bot for Dan Williams
2018-01-30  1:02 ` [PATCH v6 06/13] x86, usercopy: replace open coded stac/clac with __uaccess_{begin, end} Dan Williams
2018-01-30 22:35   ` [tip:x86/pti] x86/usercopy: Replace " tip-bot for Dan Williams
2018-01-30  1:02 ` [PATCH v6 07/13] x86, __get_user: use __uaccess_begin_nospec Dan Williams
2018-01-30 22:36   ` [tip:x86/pti] x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec tip-bot for Dan Williams
2018-01-30  1:02 ` [PATCH v6 08/13] x86, get_user: use pointer masking to limit speculation Dan Williams
2018-01-30 22:36   ` [tip:x86/pti] x86/get_user: Use " tip-bot for Dan Williams
2018-01-30  1:02 ` [PATCH v6 09/13] x86: sanitize syscall table de-references under speculation Dan Williams
2018-01-30 22:37   ` [tip:x86/pti] x86/syscall: Sanitize " tip-bot for Dan Williams
2018-01-30  1:03 ` [PATCH v6 10/13] vfs, fdtable: prevent bounds-check bypass via speculative execution Dan Williams
2018-01-30 22:37   ` [tip:x86/pti] vfs, fdtable: Prevent " tip-bot for Dan Williams
2018-01-30  1:03 ` [PATCH v6 11/13] kvm, x86: update spectre-v1 mitigation Dan Williams
2018-01-31  3:22   ` Dan Williams
2018-01-31  8:07     ` Thomas Gleixner
2018-01-31 13:49       ` Paolo Bonzini
2018-01-31 15:42         ` Thomas Gleixner
2018-01-30  1:03 ` [PATCH v6 12/13] nl80211: sanitize array index in parse_txq_params Dan Williams
2018-01-30 22:38   ` [tip:x86/pti] nl80211: Sanitize " tip-bot for Dan Williams
2018-01-30  1:03 ` [PATCH v6 13/13] x86/spectre: report get_user mitigation for spectre_v1 Dan Williams
2018-01-30 22:38   ` [tip:x86/pti] x86/spectre: Report " tip-bot for Dan Williams

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.