Merge tag 'x86_bugs_pbrsb' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Aug 2022 16:29:07 +0000 (09:29 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Aug 2022 16:29:07 +0000 (09:29 -0700)
Pull x86 eIBRS fixes from Borislav Petkov:
 "More from the CPU vulnerability nightmares front:

  Intel eIBRS machines do not sufficiently mitigate against RET
  mispredictions when doing a VM Exit therefore an additional RSB,
  one-entry stuffing is needed"

* tag 'x86_bugs_pbrsb' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/speculation: Add LFENCE to RSB fill sequence
  x86/speculation: Add RSB VM Exit protections

Documentation/admin-guide/hw-vuln/spectre.rst
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/nospec-branch.h
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kvm/vmx/vmenter.S
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h

index 9e95568..2ce2a38 100644 (file)
@@ -422,6 +422,14 @@ The possible values in this file are:
   'RSB filling'   Protection of RSB on context switch enabled
   =============   ===========================================
 
+  - EIBRS Post-barrier Return Stack Buffer (PBRSB) protection status:
+
+  ===========================  =======================================================
+  'PBRSB-eIBRS: SW sequence'   CPU is affected and protection of RSB on VMEXIT enabled
+  'PBRSB-eIBRS: Vulnerable'    CPU is vulnerable
+  'PBRSB-eIBRS: Not affected'  CPU is not affected by PBRSB
+  ===========================  =======================================================
+
 Full mitigation might require a microcode update from the CPU
 vendor. When the necessary microcode is not available, the kernel will
 report vulnerability.
index 14ed039..235dc85 100644 (file)
 #define X86_FEATURE_RETHUNK            (11*32+14) /* "" Use REturn THUNK */
 #define X86_FEATURE_UNRET              (11*32+15) /* "" AMD BTB untrain return */
 #define X86_FEATURE_USE_IBPB_FW                (11*32+16) /* "" Use IBPB during runtime firmware calls */
+#define X86_FEATURE_RSB_VMEXIT_LITE    (11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX_VNNI           (12*32+ 4) /* AVX VNNI instructions */
 #define X86_BUG_SRBDS                  X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
 #define X86_BUG_MMIO_STALE_DATA                X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
 #define X86_BUG_RETBLEED               X86_BUG(26) /* CPU is affected by RETBleed */
+#define X86_BUG_EIBRS_PBRSB            X86_BUG(27) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index 182b2a1..6674bdb 100644 (file)
                                                 * are restricted to targets in
                                                 * kernel.
                                                 */
+#define ARCH_CAP_PBRSB_NO              BIT(24) /*
+                                                * Not susceptible to Post-Barrier
+                                                * Return Stack Buffer Predictions.
+                                                */
 
 #define MSR_IA32_FLUSH_CMD             0x0000010b
 #define L1D_FLUSH                      BIT(0)  /*
index cba9420..e64fd20 100644 (file)
@@ -60,7 +60,9 @@
 774:                                           \
        add     $(BITS_PER_LONG/8) * 2, sp;     \
        dec     reg;                            \
-       jnz     771b;
+       jnz     771b;                           \
+       /* barrier for jnz misprediction */     \
+       lfence;
 
 #ifdef __ASSEMBLY__
 
 #endif
 .endm
 
+.macro ISSUE_UNBALANCED_RET_GUARD
+       ANNOTATE_INTRA_FUNCTION_CALL
+       call .Lunbalanced_ret_guard_\@
+       int3
+.Lunbalanced_ret_guard_\@:
+       add $(BITS_PER_LONG/8), %_ASM_SP
+       lfence
+.endm
+
  /*
   * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP
   * monstrosity above, manually.
   */
-.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req
+.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2
+.ifb \ftr2
        ALTERNATIVE "jmp .Lskip_rsb_\@", "", \ftr
+.else
+       ALTERNATIVE_2 "jmp .Lskip_rsb_\@", "", \ftr, "jmp .Lunbalanced_\@", \ftr2
+.endif
        __FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP)
+.Lunbalanced_\@:
+       ISSUE_UNBALANCED_RET_GUARD
 .Lskip_rsb_\@:
 .endm
 
index 6761668..9f7e751 100644 (file)
@@ -1335,6 +1335,53 @@ static void __init spec_ctrl_disable_kernel_rrsba(void)
        }
 }
 
+static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode)
+{
+       /*
+        * Similar to context switches, there are two types of RSB attacks
+        * after VM exit:
+        *
+        * 1) RSB underflow
+        *
+        * 2) Poisoned RSB entry
+        *
+        * When retpoline is enabled, both are mitigated by filling/clearing
+        * the RSB.
+        *
+        * When IBRS is enabled, while #1 would be mitigated by the IBRS branch
+        * prediction isolation protections, RSB still needs to be cleared
+        * because of #2.  Note that SMEP provides no protection here, unlike
+        * user-space-poisoned RSB entries.
+        *
+        * eIBRS should protect against RSB poisoning, but if the EIBRS_PBRSB
+        * bug is present then a LITE version of RSB protection is required,
+        * just a single call needs to retire before a RET is executed.
+        */
+       switch (mode) {
+       case SPECTRE_V2_NONE:
+               return;
+
+       case SPECTRE_V2_EIBRS_LFENCE:
+       case SPECTRE_V2_EIBRS:
+               if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
+                       setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT_LITE);
+                       pr_info("Spectre v2 / PBRSB-eIBRS: Retire a single CALL on VMEXIT\n");
+               }
+               return;
+
+       case SPECTRE_V2_EIBRS_RETPOLINE:
+       case SPECTRE_V2_RETPOLINE:
+       case SPECTRE_V2_LFENCE:
+       case SPECTRE_V2_IBRS:
+               setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT);
+               pr_info("Spectre v2 / SpectreRSB : Filling RSB on VMEXIT\n");
+               return;
+       }
+
+       pr_warn_once("Unknown Spectre v2 mode, disabling RSB mitigation at VM exit");
+       dump_stack();
+}
+
 static void __init spectre_v2_select_mitigation(void)
 {
        enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -1485,28 +1532,7 @@ static void __init spectre_v2_select_mitigation(void)
        setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
        pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");
 
-       /*
-        * Similar to context switches, there are two types of RSB attacks
-        * after vmexit:
-        *
-        * 1) RSB underflow
-        *
-        * 2) Poisoned RSB entry
-        *
-        * When retpoline is enabled, both are mitigated by filling/clearing
-        * the RSB.
-        *
-        * When IBRS is enabled, while #1 would be mitigated by the IBRS branch
-        * prediction isolation protections, RSB still needs to be cleared
-        * because of #2.  Note that SMEP provides no protection here, unlike
-        * user-space-poisoned RSB entries.
-        *
-        * eIBRS, on the other hand, has RSB-poisoning protections, so it
-        * doesn't need RSB clearing after vmexit.
-        */
-       if (boot_cpu_has(X86_FEATURE_RETPOLINE) ||
-           boot_cpu_has(X86_FEATURE_KERNEL_IBRS))
-               setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT);
+       spectre_v2_determine_rsb_fill_type_at_vmexit(mode);
 
        /*
         * Retpoline protects the kernel, but doesn't protect firmware.  IBRS
@@ -2292,6 +2318,19 @@ static char *ibpb_state(void)
        return "";
 }
 
+static char *pbrsb_eibrs_state(void)
+{
+       if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
+               if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) ||
+                   boot_cpu_has(X86_FEATURE_RSB_VMEXIT))
+                       return ", PBRSB-eIBRS: SW sequence";
+               else
+                       return ", PBRSB-eIBRS: Vulnerable";
+       } else {
+               return ", PBRSB-eIBRS: Not affected";
+       }
+}
+
 static ssize_t spectre_v2_show_state(char *buf)
 {
        if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
@@ -2304,12 +2343,13 @@ static ssize_t spectre_v2_show_state(char *buf)
            spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
                return sprintf(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
 
-       return sprintf(buf, "%s%s%s%s%s%s\n",
+       return sprintf(buf, "%s%s%s%s%s%s%s\n",
                       spectre_v2_strings[spectre_v2_enabled],
                       ibpb_state(),
                       boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
                       stibp_state(),
                       boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
+                      pbrsb_eibrs_state(),
                       spectre_v2_module_string());
 }
 
index 736262a..64a73f4 100644 (file)
@@ -1135,6 +1135,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
 #define NO_SWAPGS              BIT(6)
 #define NO_ITLB_MULTIHIT       BIT(7)
 #define NO_SPECTRE_V2          BIT(8)
+#define NO_EIBRS_PBRSB         BIT(9)
 
 #define VULNWL(vendor, family, model, whitelist)       \
        X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, whitelist)
@@ -1177,7 +1178,7 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
 
        VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
        VULNWL_INTEL(ATOM_GOLDMONT_D,           NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
+       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
 
        /*
         * Technically, swapgs isn't serializing on AMD (despite it previously
@@ -1187,7 +1188,9 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
         * good enough for our purposes.
         */
 
-       VULNWL_INTEL(ATOM_TREMONT_D,            NO_ITLB_MULTIHIT),
+       VULNWL_INTEL(ATOM_TREMONT,              NO_EIBRS_PBRSB),
+       VULNWL_INTEL(ATOM_TREMONT_L,            NO_EIBRS_PBRSB),
+       VULNWL_INTEL(ATOM_TREMONT_D,            NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
 
        /* AMD Family 0xf - 0x12 */
        VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
@@ -1365,6 +1368,11 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
                        setup_force_cpu_bug(X86_BUG_RETBLEED);
        }
 
+       if (cpu_has(c, X86_FEATURE_IBRS_ENHANCED) &&
+           !cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
+           !(ia32_cap & ARCH_CAP_PBRSB_NO))
+               setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
+
        if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
                return;
 
index 4182c7f..6de96b9 100644 (file)
@@ -227,11 +227,13 @@ SYM_INNER_LABEL(vmx_vmexit, SYM_L_GLOBAL)
         * entries and (in some cases) RSB underflow.
         *
         * eIBRS has its own protection against poisoned RSB, so it doesn't
-        * need the RSB filling sequence.  But it does need to be enabled
-        * before the first unbalanced RET.
+        * need the RSB filling sequence.  But it does need to be enabled, and a
+        * single call to retire, before the first unbalanced RET.
          */
 
-       FILL_RETURN_BUFFER %_ASM_CX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT
+       FILL_RETURN_BUFFER %_ASM_CX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT,\
+                          X86_FEATURE_RSB_VMEXIT_LITE
+
 
        pop %_ASM_ARG2  /* @flags */
        pop %_ASM_ARG1  /* @vmx */
index a77b915..8323ac5 100644 (file)
 #define X86_FEATURE_RETHUNK            (11*32+14) /* "" Use REturn THUNK */
 #define X86_FEATURE_UNRET              (11*32+15) /* "" AMD BTB untrain return */
 #define X86_FEATURE_USE_IBPB_FW                (11*32+16) /* "" Use IBPB during runtime firmware calls */
+#define X86_FEATURE_RSB_VMEXIT_LITE    (11*32+17) /* "" Fill RSB on VM-Exit when EIBRS is enabled */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX_VNNI           (12*32+ 4) /* AVX VNNI instructions */
index cc615be..e057e03 100644 (file)
                                                 * are restricted to targets in
                                                 * kernel.
                                                 */
+#define ARCH_CAP_PBRSB_NO              BIT(24) /*
+                                                * Not susceptible to Post-Barrier
+                                                * Return Stack Buffer Predictions.
+                                                */
 
 #define MSR_IA32_FLUSH_CMD             0x0000010b
 #define L1D_FLUSH                      BIT(0)  /*