]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Jan 2018 08:33:15 +0000 (09:33 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Jan 2018 08:33:15 +0000 (09:33 +0100)
added patches:
objtool-allow-alternatives-to-be-ignored.patch
objtool-detect-jumps-to-retpoline-thunks.patch
x86-pti-make-unpoison-of-pgd-for-trusted-boot-work-for-real.patch
x86-retpoline-add-initial-retpoline-support.patch
x86-spectre-add-boot-time-option-to-select-spectre-v2-mitigation.patch

queue-4.14/objtool-allow-alternatives-to-be-ignored.patch [new file with mode: 0644]
queue-4.14/objtool-detect-jumps-to-retpoline-thunks.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/x86-pti-make-unpoison-of-pgd-for-trusted-boot-work-for-real.patch [new file with mode: 0644]
queue-4.14/x86-retpoline-add-initial-retpoline-support.patch [new file with mode: 0644]
queue-4.14/x86-spectre-add-boot-time-option-to-select-spectre-v2-mitigation.patch [new file with mode: 0644]

diff --git a/queue-4.14/objtool-allow-alternatives-to-be-ignored.patch b/queue-4.14/objtool-allow-alternatives-to-be-ignored.patch
new file mode 100644 (file)
index 0000000..d38c0a1
--- /dev/null
@@ -0,0 +1,165 @@
+From 258c76059cece01bebae098e81bacb1af2edad17 Mon Sep 17 00:00:00 2001
+From: Josh Poimboeuf <jpoimboe@redhat.com>
+Date: Thu, 11 Jan 2018 21:46:24 +0000
+Subject: objtool: Allow alternatives to be ignored
+
+From: Josh Poimboeuf <jpoimboe@redhat.com>
+
+commit 258c76059cece01bebae098e81bacb1af2edad17 upstream.
+
+Getting objtool to understand retpolines is going to be a bit of a
+challenge.  For now, take advantage of the fact that retpolines are
+patched in with alternatives.  Just read the original (sane)
+non-alternative instruction, and ignore the patched-in retpoline.
+
+This allows objtool to understand the control flow *around* the
+retpoline, even if it can't yet follow what's inside.  This means the
+ORC unwinder will fail to unwind from inside a retpoline, but will work
+fine otherwise.
+
+Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: gnomes@lxorguk.ukuu.org.uk
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: thomas.lendacky@amd.com
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Jiri Kosina <jikos@kernel.org>
+Cc: Andy Lutomirski <luto@amacapital.net>
+Cc: Dave Hansen <dave.hansen@intel.com>
+Cc: Kees Cook <keescook@google.com>
+Cc: Tim Chen <tim.c.chen@linux.intel.com>
+Cc: Greg Kroah-Hartman <gregkh@linux-foundation.org>
+Cc: Paul Turner <pjt@google.com>
+Link: https://lkml.kernel.org/r/1515707194-20531-3-git-send-email-dwmw@amazon.co.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/objtool/check.c |   62 +++++++++++++++++++++++++++++++++++++++++++++-----
+ tools/objtool/check.h |    2 -
+ 2 files changed, 57 insertions(+), 7 deletions(-)
+
+--- a/tools/objtool/check.c
++++ b/tools/objtool/check.c
+@@ -428,6 +428,40 @@ static void add_ignores(struct objtool_f
+ }
+ /*
++ * FIXME: For now, just ignore any alternatives which add retpolines.  This is
++ * a temporary hack, as it doesn't allow ORC to unwind from inside a retpoline.
++ * But it at least allows objtool to understand the control flow *around* the
++ * retpoline.
++ */
++static int add_nospec_ignores(struct objtool_file *file)
++{
++      struct section *sec;
++      struct rela *rela;
++      struct instruction *insn;
++
++      sec = find_section_by_name(file->elf, ".rela.discard.nospec");
++      if (!sec)
++              return 0;
++
++      list_for_each_entry(rela, &sec->rela_list, list) {
++              if (rela->sym->type != STT_SECTION) {
++                      WARN("unexpected relocation symbol type in %s", sec->name);
++                      return -1;
++              }
++
++              insn = find_insn(file, rela->sym->sec, rela->addend);
++              if (!insn) {
++                      WARN("bad .discard.nospec entry");
++                      return -1;
++              }
++
++              insn->ignore_alts = true;
++      }
++
++      return 0;
++}
++
++/*
+  * Find the destination instructions for all jumps.
+  */
+ static int add_jump_destinations(struct objtool_file *file)
+@@ -509,11 +543,18 @@ static int add_call_destinations(struct
+                       dest_off = insn->offset + insn->len + insn->immediate;
+                       insn->call_dest = find_symbol_by_offset(insn->sec,
+                                                               dest_off);
++                      /*
++                       * FIXME: Thanks to retpolines, it's now considered
++                       * normal for a function to call within itself.  So
++                       * disable this warning for now.
++                       */
++#if 0
+                       if (!insn->call_dest) {
+                               WARN_FUNC("can't find call dest symbol at offset 0x%lx",
+                                         insn->sec, insn->offset, dest_off);
+                               return -1;
+                       }
++#endif
+               } else if (rela->sym->type == STT_SECTION) {
+                       insn->call_dest = find_symbol_by_offset(rela->sym->sec,
+                                                               rela->addend+4);
+@@ -678,12 +719,6 @@ static int add_special_section_alts(stru
+               return ret;
+       list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
+-              alt = malloc(sizeof(*alt));
+-              if (!alt) {
+-                      WARN("malloc failed");
+-                      ret = -1;
+-                      goto out;
+-              }
+               orig_insn = find_insn(file, special_alt->orig_sec,
+                                     special_alt->orig_off);
+@@ -694,6 +729,10 @@ static int add_special_section_alts(stru
+                       goto out;
+               }
++              /* Ignore retpoline alternatives. */
++              if (orig_insn->ignore_alts)
++                      continue;
++
+               new_insn = NULL;
+               if (!special_alt->group || special_alt->new_len) {
+                       new_insn = find_insn(file, special_alt->new_sec,
+@@ -719,6 +758,13 @@ static int add_special_section_alts(stru
+                               goto out;
+               }
++              alt = malloc(sizeof(*alt));
++              if (!alt) {
++                      WARN("malloc failed");
++                      ret = -1;
++                      goto out;
++              }
++
+               alt->insn = new_insn;
+               list_add_tail(&alt->list, &orig_insn->alts);
+@@ -1035,6 +1081,10 @@ static int decode_sections(struct objtoo
+       add_ignores(file);
++      ret = add_nospec_ignores(file);
++      if (ret)
++              return ret;
++
+       ret = add_jump_destinations(file);
+       if (ret)
+               return ret;
+--- a/tools/objtool/check.h
++++ b/tools/objtool/check.h
+@@ -44,7 +44,7 @@ struct instruction {
+       unsigned int len;
+       unsigned char type;
+       unsigned long immediate;
+-      bool alt_group, visited, dead_end, ignore, hint, save, restore;
++      bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts;
+       struct symbol *call_dest;
+       struct instruction *jump_dest;
+       struct list_head alts;
diff --git a/queue-4.14/objtool-detect-jumps-to-retpoline-thunks.patch b/queue-4.14/objtool-detect-jumps-to-retpoline-thunks.patch
new file mode 100644 (file)
index 0000000..8239120
--- /dev/null
@@ -0,0 +1,60 @@
+From 39b735332cb8b33a27c28592d969e4016c86c3ea Mon Sep 17 00:00:00 2001
+From: Josh Poimboeuf <jpoimboe@redhat.com>
+Date: Thu, 11 Jan 2018 21:46:23 +0000
+Subject: objtool: Detect jumps to retpoline thunks
+
+From: Josh Poimboeuf <jpoimboe@redhat.com>
+
+commit 39b735332cb8b33a27c28592d969e4016c86c3ea upstream.
+
+A direct jump to a retpoline thunk is really an indirect jump in
+disguise.  Change the objtool instruction type accordingly.
+
+Objtool needs to know where indirect branches are so it can detect
+switch statement jump tables.
+
+This fixes a bunch of warnings with CONFIG_RETPOLINE like:
+
+  arch/x86/events/intel/uncore_nhmex.o: warning: objtool: nhmex_rbox_msr_enable_event()+0x44: sibling call from callable instruction with modified stack frame
+  kernel/signal.o: warning: objtool: copy_siginfo_to_user()+0x91: sibling call from callable instruction with modified stack frame
+  ...
+
+Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: gnomes@lxorguk.ukuu.org.uk
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: thomas.lendacky@amd.com
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Jiri Kosina <jikos@kernel.org>
+Cc: Andy Lutomirski <luto@amacapital.net>
+Cc: Dave Hansen <dave.hansen@intel.com>
+Cc: Kees Cook <keescook@google.com>
+Cc: Tim Chen <tim.c.chen@linux.intel.com>
+Cc: Greg Kroah-Hartman <gregkh@linux-foundation.org>
+Cc: Paul Turner <pjt@google.com>
+Link: https://lkml.kernel.org/r/1515707194-20531-2-git-send-email-dwmw@amazon.co.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/objtool/check.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/tools/objtool/check.c
++++ b/tools/objtool/check.c
+@@ -456,6 +456,13 @@ static int add_jump_destinations(struct
+               } else if (rela->sym->sec->idx) {
+                       dest_sec = rela->sym->sec;
+                       dest_off = rela->sym->sym.st_value + rela->addend + 4;
++              } else if (strstr(rela->sym->name, "_indirect_thunk_")) {
++                      /*
++                       * Retpoline jumps are really dynamic jumps in
++                       * disguise, so convert them accordingly.
++                       */
++                      insn->type = INSN_JUMP_DYNAMIC;
++                      continue;
+               } else {
+                       /* sibling call */
+                       insn->jump_dest = 0;
index a736721c38a8c2661f6d1d1be90cb0437df96d4c..64317ef33b59dcf5a7b9056a1157b2dd215f755f 100644 (file)
@@ -98,3 +98,8 @@ x86-cpu-amd-make-lfence-a-serializing-instruction.patch
 x86-cpu-amd-use-lfence_rdtsc-in-preference-to-mfence_rdtsc.patch
 sysfs-cpu-fix-typos-in-vulnerability-documentation.patch
 x86-alternatives-fix-optimize_nops-checking.patch
+x86-pti-make-unpoison-of-pgd-for-trusted-boot-work-for-real.patch
+objtool-detect-jumps-to-retpoline-thunks.patch
+objtool-allow-alternatives-to-be-ignored.patch
+x86-retpoline-add-initial-retpoline-support.patch
+x86-spectre-add-boot-time-option-to-select-spectre-v2-mitigation.patch
diff --git a/queue-4.14/x86-pti-make-unpoison-of-pgd-for-trusted-boot-work-for-real.patch b/queue-4.14/x86-pti-make-unpoison-of-pgd-for-trusted-boot-work-for-real.patch
new file mode 100644 (file)
index 0000000..f8d4186
--- /dev/null
@@ -0,0 +1,74 @@
+From 445b69e3b75e42362a5bdc13c8b8f61599e2228a Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave.hansen@linux.intel.com>
+Date: Wed, 10 Jan 2018 14:49:39 -0800
+Subject: x86/pti: Make unpoison of pgd for trusted boot work for real
+
+From: Dave Hansen <dave.hansen@linux.intel.com>
+
+commit 445b69e3b75e42362a5bdc13c8b8f61599e2228a upstream.
+
+The inital fix for trusted boot and PTI potentially misses the pgd clearing
+if pud_alloc() sets a PGD.  It probably works in *practice* because for two
+adjacent calls to map_tboot_page() that share a PGD entry, the first will
+clear NX, *then* allocate and set the PGD (without NX clear).  The second
+call will *not* allocate but will clear the NX bit.
+
+Defer the NX clearing to a point after it is known that all top-level
+allocations have occurred.  Add a comment to clarify why.
+
+[ tglx: Massaged changelog ]
+
+Fixes: 262b6b30087 ("x86/tboot: Unbreak tboot with PTI enabled")
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Jon Masters <jcm@redhat.com>
+Cc: "Tim Chen" <tim.c.chen@linux.intel.com>
+Cc: gnomes@lxorguk.ukuu.org.uk
+Cc: peterz@infradead.org
+Cc: ning.sun@intel.com
+Cc: tboot-devel@lists.sourceforge.net
+Cc: andi@firstfloor.org
+Cc: luto@kernel.org
+Cc: law@redhat.com
+Cc: pbonzini@redhat.com
+Cc: torvalds@linux-foundation.org
+Cc: gregkh@linux-foundation.org
+Cc: dwmw@amazon.co.uk
+Cc: nickc@redhat.com
+Cc: stable@vger.kernel.org
+Link: https://lkml.kernel.org/r/20180110224939.2695CD47@viggo.jf.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/tboot.c |   12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/tboot.c
++++ b/arch/x86/kernel/tboot.c
+@@ -127,7 +127,6 @@ static int map_tboot_page(unsigned long
+       p4d = p4d_alloc(&tboot_mm, pgd, vaddr);
+       if (!p4d)
+               return -1;
+-      pgd->pgd &= ~_PAGE_NX;
+       pud = pud_alloc(&tboot_mm, p4d, vaddr);
+       if (!pud)
+               return -1;
+@@ -139,6 +138,17 @@ static int map_tboot_page(unsigned long
+               return -1;
+       set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot));
+       pte_unmap(pte);
++
++      /*
++       * PTI poisons low addresses in the kernel page tables in the
++       * name of making them unusable for userspace.  To execute
++       * code at such a low address, the poison must be cleared.
++       *
++       * Note: 'pgd' actually gets set in p4d_alloc() _or_
++       * pud_alloc() depending on 4/5-level paging.
++       */
++      pgd->pgd &= ~_PAGE_NX;
++
+       return 0;
+ }
diff --git a/queue-4.14/x86-retpoline-add-initial-retpoline-support.patch b/queue-4.14/x86-retpoline-add-initial-retpoline-support.patch
new file mode 100644 (file)
index 0000000..13e592e
--- /dev/null
@@ -0,0 +1,356 @@
+From 76b043848fd22dbf7f8bf3a1452f8c70d557b860 Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw@amazon.co.uk>
+Date: Thu, 11 Jan 2018 21:46:25 +0000
+Subject: x86/retpoline: Add initial retpoline support
+
+From: David Woodhouse <dwmw@amazon.co.uk>
+
+commit 76b043848fd22dbf7f8bf3a1452f8c70d557b860 upstream.
+
+Enable the use of -mindirect-branch=thunk-extern in newer GCC, and provide
+the corresponding thunks. Provide assembler macros for invoking the thunks
+in the same way that GCC does, from native and inline assembler.
+
+This adds X86_FEATURE_RETPOLINE and sets it by default on all CPUs. In
+some circumstances, IBRS microcode features may be used instead, and the
+retpoline can be disabled.
+
+On AMD CPUs if lfence is serialising, the retpoline can be dramatically
+simplified to a simple "lfence; jmp *\reg". A future patch, after it has
+been verified that lfence really is serialising in all circumstances, can
+enable this by setting the X86_FEATURE_RETPOLINE_AMD feature bit in addition
+to X86_FEATURE_RETPOLINE.
+
+Do not align the retpoline in the altinstr section, because there is no
+guarantee that it stays aligned when it's copied over the oldinstr during
+alternative patching.
+
+[ Andi Kleen: Rename the macros, add CONFIG_RETPOLINE option, export thunks]
+[ tglx: Put actual function CALL/JMP in front of the macros, convert to
+       symbolic labels ]
+[ dwmw2: Convert back to numeric labels, merge objtool fixes ]
+
+Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Arjan van de Ven <arjan@linux.intel.com>
+Acked-by: Ingo Molnar <mingo@kernel.org>
+Cc: gnomes@lxorguk.ukuu.org.uk
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: thomas.lendacky@amd.com
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Jiri Kosina <jikos@kernel.org>
+Cc: Andy Lutomirski <luto@amacapital.net>
+Cc: Dave Hansen <dave.hansen@intel.com>
+Cc: Kees Cook <keescook@google.com>
+Cc: Tim Chen <tim.c.chen@linux.intel.com>
+Cc: Greg Kroah-Hartman <gregkh@linux-foundation.org>
+Cc: Paul Turner <pjt@google.com>
+Link: https://lkml.kernel.org/r/1515707194-20531-4-git-send-email-dwmw@amazon.co.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/Kconfig                      |   13 +++
+ arch/x86/Makefile                     |   10 ++
+ arch/x86/include/asm/asm-prototypes.h |   25 ++++++
+ arch/x86/include/asm/cpufeatures.h    |    2 
+ arch/x86/include/asm/nospec-branch.h  |  128 ++++++++++++++++++++++++++++++++++
+ arch/x86/kernel/cpu/common.c          |    4 +
+ arch/x86/lib/Makefile                 |    1 
+ arch/x86/lib/retpoline.S              |   48 ++++++++++++
+ 8 files changed, 231 insertions(+)
+
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -429,6 +429,19 @@ config GOLDFISH
+        def_bool y
+        depends on X86_GOLDFISH
++config RETPOLINE
++      bool "Avoid speculative indirect branches in kernel"
++      default y
++      help
++        Compile kernel with the retpoline compiler options to guard against
++        kernel-to-user data leaks by avoiding speculative indirect
++        branches. Requires a compiler with -mindirect-branch=thunk-extern
++        support for full protection. The kernel may run slower.
++
++        Without compiler support, at least indirect branches in assembler
++        code are eliminated. Since this includes the syscall entry path,
++        it is not entirely pointless.
++
+ config INTEL_RDT
+       bool "Intel Resource Director Technology support"
+       default n
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -235,6 +235,16 @@ KBUILD_CFLAGS += -Wno-sign-compare
+ #
+ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
++# Avoid indirect branches in kernel to deal with Spectre
++ifdef CONFIG_RETPOLINE
++    RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register)
++    ifneq ($(RETPOLINE_CFLAGS),)
++        KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE
++    else
++        $(warning CONFIG_RETPOLINE=y, but not supported by the compiler. Toolchain update recommended.)
++    endif
++endif
++
+ archscripts: scripts_basic
+       $(Q)$(MAKE) $(build)=arch/x86/tools relocs
+--- a/arch/x86/include/asm/asm-prototypes.h
++++ b/arch/x86/include/asm/asm-prototypes.h
+@@ -11,7 +11,32 @@
+ #include <asm/pgtable.h>
+ #include <asm/special_insns.h>
+ #include <asm/preempt.h>
++#include <asm/asm.h>
+ #ifndef CONFIG_X86_CMPXCHG64
+ extern void cmpxchg8b_emu(void);
+ #endif
++
++#ifdef CONFIG_RETPOLINE
++#ifdef CONFIG_X86_32
++#define INDIRECT_THUNK(reg) extern asmlinkage void __x86_indirect_thunk_e ## reg(void);
++#else
++#define INDIRECT_THUNK(reg) extern asmlinkage void __x86_indirect_thunk_r ## reg(void);
++INDIRECT_THUNK(8)
++INDIRECT_THUNK(9)
++INDIRECT_THUNK(10)
++INDIRECT_THUNK(11)
++INDIRECT_THUNK(12)
++INDIRECT_THUNK(13)
++INDIRECT_THUNK(14)
++INDIRECT_THUNK(15)
++#endif
++INDIRECT_THUNK(ax)
++INDIRECT_THUNK(bx)
++INDIRECT_THUNK(cx)
++INDIRECT_THUNK(dx)
++INDIRECT_THUNK(si)
++INDIRECT_THUNK(di)
++INDIRECT_THUNK(bp)
++INDIRECT_THUNK(sp)
++#endif /* CONFIG_RETPOLINE */
+--- a/arch/x86/include/asm/cpufeatures.h
++++ b/arch/x86/include/asm/cpufeatures.h
+@@ -203,6 +203,8 @@
+ #define X86_FEATURE_PROC_FEEDBACK     ( 7*32+ 9) /* AMD ProcFeedbackInterface */
+ #define X86_FEATURE_SME                       ( 7*32+10) /* AMD Secure Memory Encryption */
+ #define X86_FEATURE_PTI                       ( 7*32+11) /* Kernel Page Table Isolation enabled */
++#define X86_FEATURE_RETPOLINE         ( 7*32+12) /* Generic Retpoline mitigation for Spectre variant 2 */
++#define X86_FEATURE_RETPOLINE_AMD     ( 7*32+13) /* AMD Retpoline mitigation for Spectre variant 2 */
+ #define X86_FEATURE_INTEL_PPIN                ( 7*32+14) /* Intel Processor Inventory Number */
+ #define X86_FEATURE_INTEL_PT          ( 7*32+15) /* Intel Processor Trace */
+ #define X86_FEATURE_AVX512_4VNNIW     ( 7*32+16) /* AVX-512 Neural Network Instructions */
+--- /dev/null
++++ b/arch/x86/include/asm/nospec-branch.h
+@@ -0,0 +1,128 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++#ifndef __NOSPEC_BRANCH_H__
++#define __NOSPEC_BRANCH_H__
++
++#include <asm/alternative.h>
++#include <asm/alternative-asm.h>
++#include <asm/cpufeatures.h>
++
++#ifdef __ASSEMBLY__
++
++/*
++ * This should be used immediately before a retpoline alternative.  It tells
++ * objtool where the retpolines are so that it can make sense of the control
++ * flow by just reading the original instruction(s) and ignoring the
++ * alternatives.
++ */
++.macro ANNOTATE_NOSPEC_ALTERNATIVE
++      .Lannotate_\@:
++      .pushsection .discard.nospec
++      .long .Lannotate_\@ - .
++      .popsection
++.endm
++
++/*
++ * These are the bare retpoline primitives for indirect jmp and call.
++ * Do not use these directly; they only exist to make the ALTERNATIVE
++ * invocation below less ugly.
++ */
++.macro RETPOLINE_JMP reg:req
++      call    .Ldo_rop_\@
++.Lspec_trap_\@:
++      pause
++      jmp     .Lspec_trap_\@
++.Ldo_rop_\@:
++      mov     \reg, (%_ASM_SP)
++      ret
++.endm
++
++/*
++ * This is a wrapper around RETPOLINE_JMP so the called function in reg
++ * returns to the instruction after the macro.
++ */
++.macro RETPOLINE_CALL reg:req
++      jmp     .Ldo_call_\@
++.Ldo_retpoline_jmp_\@:
++      RETPOLINE_JMP \reg
++.Ldo_call_\@:
++      call    .Ldo_retpoline_jmp_\@
++.endm
++
++/*
++ * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple
++ * indirect jmp/call which may be susceptible to the Spectre variant 2
++ * attack.
++ */
++.macro JMP_NOSPEC reg:req
++#ifdef CONFIG_RETPOLINE
++      ANNOTATE_NOSPEC_ALTERNATIVE
++      ALTERNATIVE_2 __stringify(jmp *\reg),                           \
++              __stringify(RETPOLINE_JMP \reg), X86_FEATURE_RETPOLINE, \
++              __stringify(lfence; jmp *\reg), X86_FEATURE_RETPOLINE_AMD
++#else
++      jmp     *\reg
++#endif
++.endm
++
++.macro CALL_NOSPEC reg:req
++#ifdef CONFIG_RETPOLINE
++      ANNOTATE_NOSPEC_ALTERNATIVE
++      ALTERNATIVE_2 __stringify(call *\reg),                          \
++              __stringify(RETPOLINE_CALL \reg), X86_FEATURE_RETPOLINE,\
++              __stringify(lfence; call *\reg), X86_FEATURE_RETPOLINE_AMD
++#else
++      call    *\reg
++#endif
++.endm
++
++#else /* __ASSEMBLY__ */
++
++#define ANNOTATE_NOSPEC_ALTERNATIVE                           \
++      "999:\n\t"                                              \
++      ".pushsection .discard.nospec\n\t"                      \
++      ".long 999b - .\n\t"                                    \
++      ".popsection\n\t"
++
++#if defined(CONFIG_X86_64) && defined(RETPOLINE)
++
++/*
++ * Since the inline asm uses the %V modifier which is only in newer GCC,
++ * the 64-bit one is dependent on RETPOLINE not CONFIG_RETPOLINE.
++ */
++# define CALL_NOSPEC                                          \
++      ANNOTATE_NOSPEC_ALTERNATIVE                             \
++      ALTERNATIVE(                                            \
++      "call *%[thunk_target]\n",                              \
++      "call __x86_indirect_thunk_%V[thunk_target]\n",         \
++      X86_FEATURE_RETPOLINE)
++# define THUNK_TARGET(addr) [thunk_target] "r" (addr)
++
++#elif defined(CONFIG_X86_32) && defined(CONFIG_RETPOLINE)
++/*
++ * For i386 we use the original ret-equivalent retpoline, because
++ * otherwise we'll run out of registers. We don't care about CET
++ * here, anyway.
++ */
++# define CALL_NOSPEC ALTERNATIVE("call *%[thunk_target]\n",   \
++      "       jmp    904f;\n"                                 \
++      "       .align 16\n"                                    \
++      "901:   call   903f;\n"                                 \
++      "902:   pause;\n"                                       \
++      "       jmp    902b;\n"                                 \
++      "       .align 16\n"                                    \
++      "903:   addl   $4, %%esp;\n"                            \
++      "       pushl  %[thunk_target];\n"                      \
++      "       ret;\n"                                         \
++      "       .align 16\n"                                    \
++      "904:   call   901b;\n",                                \
++      X86_FEATURE_RETPOLINE)
++
++# define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
++#else /* No retpoline */
++# define CALL_NOSPEC "call *%[thunk_target]\n"
++# define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
++#endif
++
++#endif /* __ASSEMBLY__ */
++#endif /* __NOSPEC_BRANCH_H__ */
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -905,6 +905,10 @@ static void __init early_identify_cpu(st
+       setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
+       setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
++#ifdef CONFIG_RETPOLINE
++      setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
++#endif
++
+       fpu__init_system(c);
+ #ifdef CONFIG_X86_32
+--- a/arch/x86/lib/Makefile
++++ b/arch/x86/lib/Makefile
+@@ -26,6 +26,7 @@ lib-y += memcpy_$(BITS).o
+ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+ lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
+ lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
++lib-$(CONFIG_RETPOLINE) += retpoline.o
+ obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
+--- /dev/null
++++ b/arch/x86/lib/retpoline.S
+@@ -0,0 +1,48 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++#include <linux/stringify.h>
++#include <linux/linkage.h>
++#include <asm/dwarf2.h>
++#include <asm/cpufeatures.h>
++#include <asm/alternative-asm.h>
++#include <asm/export.h>
++#include <asm/nospec-branch.h>
++
++.macro THUNK reg
++      .section .text.__x86.indirect_thunk.\reg
++
++ENTRY(__x86_indirect_thunk_\reg)
++      CFI_STARTPROC
++      JMP_NOSPEC %\reg
++      CFI_ENDPROC
++ENDPROC(__x86_indirect_thunk_\reg)
++.endm
++
++/*
++ * Despite being an assembler file we can't just use .irp here
++ * because __KSYM_DEPS__ only uses the C preprocessor and would
++ * only see one instance of "__x86_indirect_thunk_\reg" rather
++ * than one per register with the correct names. So we do it
++ * the simple and nasty way...
++ */
++#define EXPORT_THUNK(reg) EXPORT_SYMBOL(__x86_indirect_thunk_ ## reg)
++#define GENERATE_THUNK(reg) THUNK reg ; EXPORT_THUNK(reg)
++
++GENERATE_THUNK(_ASM_AX)
++GENERATE_THUNK(_ASM_BX)
++GENERATE_THUNK(_ASM_CX)
++GENERATE_THUNK(_ASM_DX)
++GENERATE_THUNK(_ASM_SI)
++GENERATE_THUNK(_ASM_DI)
++GENERATE_THUNK(_ASM_BP)
++GENERATE_THUNK(_ASM_SP)
++#ifdef CONFIG_64BIT
++GENERATE_THUNK(r8)
++GENERATE_THUNK(r9)
++GENERATE_THUNK(r10)
++GENERATE_THUNK(r11)
++GENERATE_THUNK(r12)
++GENERATE_THUNK(r13)
++GENERATE_THUNK(r14)
++GENERATE_THUNK(r15)
++#endif
diff --git a/queue-4.14/x86-spectre-add-boot-time-option-to-select-spectre-v2-mitigation.patch b/queue-4.14/x86-spectre-add-boot-time-option-to-select-spectre-v2-mitigation.patch
new file mode 100644 (file)
index 0000000..ea4ddda
--- /dev/null
@@ -0,0 +1,317 @@
+From da285121560e769cc31797bba6422eea71d473e0 Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw@amazon.co.uk>
+Date: Thu, 11 Jan 2018 21:46:26 +0000
+Subject: x86/spectre: Add boot time option to select Spectre v2 mitigation
+
+From: David Woodhouse <dwmw@amazon.co.uk>
+
+commit da285121560e769cc31797bba6422eea71d473e0 upstream.
+
+Add a spectre_v2= option to select the mitigation used for the indirect
+branch speculation vulnerability.
+
+Currently, the only option available is retpoline, in its various forms.
+This will be expanded to cover the new IBRS/IBPB microcode features.
+
+The RETPOLINE_AMD feature relies on a serializing LFENCE for speculation
+control. For AMD hardware, only set RETPOLINE_AMD if LFENCE is a
+serializing instruction, which is indicated by the LFENCE_RDTSC feature.
+
+[ tglx: Folded back the LFENCE/AMD fixes and reworked it so IBRS
+       integration becomes simple ]
+
+Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: gnomes@lxorguk.ukuu.org.uk
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: thomas.lendacky@amd.com
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Jiri Kosina <jikos@kernel.org>
+Cc: Andy Lutomirski <luto@amacapital.net>
+Cc: Dave Hansen <dave.hansen@intel.com>
+Cc: Kees Cook <keescook@google.com>
+Cc: Tim Chen <tim.c.chen@linux.intel.com>
+Cc: Greg Kroah-Hartman <gregkh@linux-foundation.org>
+Cc: Paul Turner <pjt@google.com>
+Link: https://lkml.kernel.org/r/1515707194-20531-5-git-send-email-dwmw@amazon.co.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ Documentation/admin-guide/kernel-parameters.txt |   28 ++++
+ arch/x86/include/asm/nospec-branch.h            |   10 +
+ arch/x86/kernel/cpu/bugs.c                      |  158 +++++++++++++++++++++++-
+ arch/x86/kernel/cpu/common.c                    |    4 
+ 4 files changed, 195 insertions(+), 5 deletions(-)
+
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -2599,6 +2599,11 @@
+       nosmt           [KNL,S390] Disable symmetric multithreading (SMT).
+                       Equivalent to smt=1.
++      nospectre_v2    [X86] Disable all mitigations for the Spectre variant 2
++                      (indirect branch prediction) vulnerability. System may
++                      allow data leaks with this option, which is equivalent
++                      to spectre_v2=off.
++
+       noxsave         [BUGS=X86] Disables x86 extended register state save
+                       and restore using xsave. The kernel will fallback to
+                       enabling legacy floating-point and sse state.
+@@ -3908,6 +3913,29 @@
+       sonypi.*=       [HW] Sony Programmable I/O Control Device driver
+                       See Documentation/laptops/sonypi.txt
++      spectre_v2=     [X86] Control mitigation of Spectre variant 2
++                      (indirect branch speculation) vulnerability.
++
++                      on   - unconditionally enable
++                      off  - unconditionally disable
++                      auto - kernel detects whether your CPU model is
++                             vulnerable
++
++                      Selecting 'on' will, and 'auto' may, choose a
++                      mitigation method at run time according to the
++                      CPU, the available microcode, the setting of the
++                      CONFIG_RETPOLINE configuration option, and the
++                      compiler with which the kernel was built.
++
++                      Specific mitigations can also be selected manually:
++
++                      retpoline         - replace indirect branches
++                      retpoline,generic - google's original retpoline
++                      retpoline,amd     - AMD-specific minimal thunk
++
++                      Not specifying this option is equivalent to
++                      spectre_v2=auto.
++
+       spia_io_base=   [HW,MTD]
+       spia_fio_base=
+       spia_pedr=
+--- a/arch/x86/include/asm/nospec-branch.h
++++ b/arch/x86/include/asm/nospec-branch.h
+@@ -124,5 +124,15 @@
+ # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
+ #endif
++/* The Spectre V2 mitigation variants */
++enum spectre_v2_mitigation {
++      SPECTRE_V2_NONE,
++      SPECTRE_V2_RETPOLINE_MINIMAL,
++      SPECTRE_V2_RETPOLINE_MINIMAL_AMD,
++      SPECTRE_V2_RETPOLINE_GENERIC,
++      SPECTRE_V2_RETPOLINE_AMD,
++      SPECTRE_V2_IBRS,
++};
++
+ #endif /* __ASSEMBLY__ */
+ #endif /* __NOSPEC_BRANCH_H__ */
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -11,6 +11,9 @@
+ #include <linux/init.h>
+ #include <linux/utsname.h>
+ #include <linux/cpu.h>
++
++#include <asm/nospec-branch.h>
++#include <asm/cmdline.h>
+ #include <asm/bugs.h>
+ #include <asm/processor.h>
+ #include <asm/processor-flags.h>
+@@ -21,6 +24,8 @@
+ #include <asm/pgtable.h>
+ #include <asm/set_memory.h>
++static void __init spectre_v2_select_mitigation(void);
++
+ void __init check_bugs(void)
+ {
+       identify_boot_cpu();
+@@ -30,6 +35,9 @@ void __init check_bugs(void)
+               print_cpu_info(&boot_cpu_data);
+       }
++      /* Select the proper spectre mitigation before patching alternatives */
++      spectre_v2_select_mitigation();
++
+ #ifdef CONFIG_X86_32
+       /*
+        * Check whether we are able to run this kernel safely on SMP.
+@@ -62,6 +70,153 @@ void __init check_bugs(void)
+ #endif
+ }
++/* The kernel command line selection */
++enum spectre_v2_mitigation_cmd {
++      SPECTRE_V2_CMD_NONE,
++      SPECTRE_V2_CMD_AUTO,
++      SPECTRE_V2_CMD_FORCE,
++      SPECTRE_V2_CMD_RETPOLINE,
++      SPECTRE_V2_CMD_RETPOLINE_GENERIC,
++      SPECTRE_V2_CMD_RETPOLINE_AMD,
++};
++
++static const char *spectre_v2_strings[] = {
++      [SPECTRE_V2_NONE]                       = "Vulnerable",
++      [SPECTRE_V2_RETPOLINE_MINIMAL]          = "Vulnerable: Minimal generic ASM retpoline",
++      [SPECTRE_V2_RETPOLINE_MINIMAL_AMD]      = "Vulnerable: Minimal AMD ASM retpoline",
++      [SPECTRE_V2_RETPOLINE_GENERIC]          = "Mitigation: Full generic retpoline",
++      [SPECTRE_V2_RETPOLINE_AMD]              = "Mitigation: Full AMD retpoline",
++};
++
++#undef pr_fmt
++#define pr_fmt(fmt)     "Spectre V2 mitigation: " fmt
++
++static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE;
++
++static void __init spec2_print_if_insecure(const char *reason)
++{
++      if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
++              pr_info("%s\n", reason);
++}
++
++static void __init spec2_print_if_secure(const char *reason)
++{
++      if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
++              pr_info("%s\n", reason);
++}
++
++static inline bool retp_compiler(void)
++{
++      return __is_defined(RETPOLINE);
++}
++
++static inline bool match_option(const char *arg, int arglen, const char *opt)
++{
++      int len = strlen(opt);
++
++      return len == arglen && !strncmp(arg, opt, len);
++}
++
++static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
++{
++      char arg[20];
++      int ret;
++
++      ret = cmdline_find_option(boot_command_line, "spectre_v2", arg,
++                                sizeof(arg));
++      if (ret > 0)  {
++              if (match_option(arg, ret, "off")) {
++                      goto disable;
++              } else if (match_option(arg, ret, "on")) {
++                      spec2_print_if_secure("force enabled on command line.");
++                      return SPECTRE_V2_CMD_FORCE;
++              } else if (match_option(arg, ret, "retpoline")) {
++                      spec2_print_if_insecure("retpoline selected on command line.");
++                      return SPECTRE_V2_CMD_RETPOLINE;
++              } else if (match_option(arg, ret, "retpoline,amd")) {
++                      if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
++                              pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n");
++                              return SPECTRE_V2_CMD_AUTO;
++                      }
++                      spec2_print_if_insecure("AMD retpoline selected on command line.");
++                      return SPECTRE_V2_CMD_RETPOLINE_AMD;
++              } else if (match_option(arg, ret, "retpoline,generic")) {
++                      spec2_print_if_insecure("generic retpoline selected on command line.");
++                      return SPECTRE_V2_CMD_RETPOLINE_GENERIC;
++              } else if (match_option(arg, ret, "auto")) {
++                      return SPECTRE_V2_CMD_AUTO;
++              }
++      }
++
++      if (!cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
++              return SPECTRE_V2_CMD_AUTO;
++disable:
++      spec2_print_if_insecure("disabled on command line.");
++      return SPECTRE_V2_CMD_NONE;
++}
++
++static void __init spectre_v2_select_mitigation(void)
++{
++      enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
++      enum spectre_v2_mitigation mode = SPECTRE_V2_NONE;
++
++      /*
++       * If the CPU is not affected and the command line mode is NONE or AUTO
++       * then nothing to do.
++       */
++      if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2) &&
++          (cmd == SPECTRE_V2_CMD_NONE || cmd == SPECTRE_V2_CMD_AUTO))
++              return;
++
++      switch (cmd) {
++      case SPECTRE_V2_CMD_NONE:
++              return;
++
++      case SPECTRE_V2_CMD_FORCE:
++              /* FALLTRHU */
++      case SPECTRE_V2_CMD_AUTO:
++              goto retpoline_auto;
++
++      case SPECTRE_V2_CMD_RETPOLINE_AMD:
++              if (IS_ENABLED(CONFIG_RETPOLINE))
++                      goto retpoline_amd;
++              break;
++      case SPECTRE_V2_CMD_RETPOLINE_GENERIC:
++              if (IS_ENABLED(CONFIG_RETPOLINE))
++                      goto retpoline_generic;
++              break;
++      case SPECTRE_V2_CMD_RETPOLINE:
++              if (IS_ENABLED(CONFIG_RETPOLINE))
++                      goto retpoline_auto;
++              break;
++      }
++      pr_err("kernel not compiled with retpoline; no mitigation available!");
++      return;
++
++retpoline_auto:
++      if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
++      retpoline_amd:
++              if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) {
++                      pr_err("LFENCE not serializing. Switching to generic retpoline\n");
++                      goto retpoline_generic;
++              }
++              mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD :
++                                       SPECTRE_V2_RETPOLINE_MINIMAL_AMD;
++              setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD);
++              setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
++      } else {
++      retpoline_generic:
++              mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC :
++                                       SPECTRE_V2_RETPOLINE_MINIMAL;
++              setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
++      }
++
++      spectre_v2_enabled = mode;
++      pr_info("%s\n", spectre_v2_strings[mode]);
++}
++
++#undef pr_fmt
++
+ #ifdef CONFIG_SYSFS
+ ssize_t cpu_show_meltdown(struct device *dev,
+                         struct device_attribute *attr, char *buf)
+@@ -86,6 +241,7 @@ ssize_t cpu_show_spectre_v2(struct devic
+ {
+       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
+               return sprintf(buf, "Not affected\n");
+-      return sprintf(buf, "Vulnerable\n");
++
++      return sprintf(buf, "%s\n", spectre_v2_strings[spectre_v2_enabled]);
+ }
+ #endif
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -905,10 +905,6 @@ static void __init early_identify_cpu(st
+       setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
+       setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
+-#ifdef CONFIG_RETPOLINE
+-      setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
+-#endif
+-
+       fpu__init_system(c);
+ #ifdef CONFIG_X86_32