History

x86/bugs: Report Intel retbleed vulnerability

Skylake suffers from RSB underflow speculation issues; report this vulnerability and it's mitigation (spectre_v2=ibrs). [jpoimboe: cleanups, eibrs]

Peter Zijlstra committed 4 years ago

Commit 6ad0ad21 parent 166115c3 files · +46 −18Browse files

Unified · Split

3 files
  1. arch/x86/include/asm/msr-index.h +1 −0
  2. arch/x86/kernel/cpu/bugs.c +33 −6
  3. arch/x86/kernel/cpu/common.c +12 −12
arch/x86/include/asm/msr-index.h+1−0
@@ -93,6 +93,7 @@ · 92 unmodified lines
9393 #define MSR_IA32_ARCH_CAPABILITIES 0x0000010a
9494 #define ARCH_CAP_RDCL_NO BIT(0) /* Not susceptible to Meltdown */
9595 #define ARCH_CAP_IBRS_ALL BIT(1) /* Enhanced IBRS support */
96+#define ARCH_CAP_RSBA BIT(2) /* RET may use alternative branch predictors */
9697 #define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH BIT(3) /* Skip L1D flush on vmentry */
9798 #define ARCH_CAP_SSB_NO BIT(4) /*
9899 * Not susceptible to Speculative Store Bypass
arch/x86/kernel/cpu/bugs.c+33−6
@@ -790,12 +790,17 @@ static int __init nospectre_v1_cmdline(char *str) · 789 unmodified lines
790790 }
791791 early_param("nospectre_v1", nospectre_v1_cmdline);
792792
793+static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
794+ SPECTRE_V2_NONE;
795+
793796 #undef pr_fmt
794797 #define pr_fmt(fmt) "RETBleed: " fmt
795798
796799 enum retbleed_mitigation {
797800 RETBLEED_MITIGATION_NONE,
798801 RETBLEED_MITIGATION_UNRET,
802+ RETBLEED_MITIGATION_IBRS,
803+ RETBLEED_MITIGATION_EIBRS,
799804 };
800805
801806 enum retbleed_mitigation_cmd {
@@ -807,6 +812,8 @@ enum retbleed_mitigation_cmd { · 5 unmodified lines
807812 const char * const retbleed_strings[] = {
808813 [RETBLEED_MITIGATION_NONE] = "Vulnerable",
809814 [RETBLEED_MITIGATION_UNRET] = "Mitigation: untrained return thunk",
815+ [RETBLEED_MITIGATION_IBRS] = "Mitigation: IBRS",
816+ [RETBLEED_MITIGATION_EIBRS] = "Mitigation: Enhanced IBRS",
810817 };
811818
812819 static enum retbleed_mitigation retbleed_mitigation __ro_after_init =
@@ -849,6 +856,7 @@ early_param("retbleed", retbleed_parse_cmdline); · 36 unmodified lines
849856
850857 #define RETBLEED_UNTRAIN_MSG "WARNING: BTB untrained return thunk mitigation is only effective on AMD/Hygon!\n"
851858 #define RETBLEED_COMPILER_MSG "WARNING: kernel not compiled with RETPOLINE or -mfunction-return capable compiler!\n"
859+#define RETBLEED_INTEL_MSG "WARNING: Spectre v2 mitigation leaves CPU vulnerable to RETBleed attacks, data leaks possible!\n"
852860
853861 static void __init retbleed_select_mitigation(void)
854862 {
@@ -865,12 +873,15 @@ static void __init retbleed_select_mitigation(void) · 10 unmodified lines
865873
866874 case RETBLEED_CMD_AUTO:
867875 default:
868− if (!boot_cpu_has_bug(X86_BUG_RETBLEED))
869− break;
870−
871876 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
872877 boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
873878 retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
879+
880+ /*
881+ * The Intel mitigation (IBRS) was already selected in
882+ * spectre_v2_select_mitigation().
883+ */
884+
874885 break;
875886 }
876887
@@ -900,15 +911,31 @@ static void __init retbleed_select_mitigation(void) · 23 unmodified lines
900911 break;
901912 }
902913
914+ /*
915+ * Let IBRS trump all on Intel without affecting the effects of the
916+ * retbleed= cmdline option.
917+ */
918+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
919+ switch (spectre_v2_enabled) {
920+ case SPECTRE_V2_IBRS:
921+ retbleed_mitigation = RETBLEED_MITIGATION_IBRS;
922+ break;
923+ case SPECTRE_V2_EIBRS:
924+ case SPECTRE_V2_EIBRS_RETPOLINE:
925+ case SPECTRE_V2_EIBRS_LFENCE:
926+ retbleed_mitigation = RETBLEED_MITIGATION_EIBRS;
927+ break;
928+ default:
929+ pr_err(RETBLEED_INTEL_MSG);
930+ }
931+ }
932+
903933 pr_info("%s\n", retbleed_strings[retbleed_mitigation]);
904934 }
905935
906936 #undef pr_fmt
907937 #define pr_fmt(fmt) "Spectre V2 : " fmt
908938
909−static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
910− SPECTRE_V2_NONE;
911−
912939 static enum spectre_v2_user_mitigation spectre_v2_user_stibp __ro_after_init =
913940 SPECTRE_V2_USER_NONE;
914941 static enum spectre_v2_user_mitigation spectre_v2_user_ibpb __ro_after_init =
arch/x86/kernel/cpu/common.c+12−12
@@ -1237,24 +1237,24 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { · 1236 unmodified lines
12371237 VULNBL_INTEL_STEPPINGS(BROADWELL_G, X86_STEPPING_ANY, SRBDS),
12381238 VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO),
12391239 VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS),
1240− VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPINGS(0x3, 0x3), SRBDS | MMIO),
1240+ VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPINGS(0x3, 0x3), SRBDS | MMIO | RETBLEED),
12411241 VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS),
12421242 VULNBL_INTEL_STEPPINGS(SKYLAKE_X, BIT(3) | BIT(4) | BIT(6) |
1243− BIT(7) | BIT(0xB), MMIO),
1244− VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPINGS(0x3, 0x3), SRBDS | MMIO),
1243+ BIT(7) | BIT(0xB), MMIO | RETBLEED),
1244+ VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPINGS(0x3, 0x3), SRBDS | MMIO | RETBLEED),
12451245 VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, SRBDS),
1246− VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPINGS(0x9, 0xC), SRBDS | MMIO),
1246+ VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPINGS(0x9, 0xC), SRBDS | MMIO | RETBLEED),
12471247 VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPINGS(0x0, 0x8), SRBDS),
1248− VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPINGS(0x9, 0xD), SRBDS | MMIO),
1248+ VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPINGS(0x9, 0xD), SRBDS | MMIO | RETBLEED),
12491249 VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPINGS(0x0, 0x8), SRBDS),
1250− VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPINGS(0x5, 0x5), MMIO | MMIO_SBDS),
1250+ VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPINGS(0x5, 0x5), MMIO | MMIO_SBDS | RETBLEED),
12511251 VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPINGS(0x1, 0x1), MMIO),
12521252 VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x4, 0x6), MMIO),
1253− VULNBL_INTEL_STEPPINGS(COMETLAKE, BIT(2) | BIT(3) | BIT(5), MMIO | MMIO_SBDS),
1254− VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS),
1255− VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO),
1256− VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS),
1257− VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPINGS(0x1, 0x1), MMIO),
1253+ VULNBL_INTEL_STEPPINGS(COMETLAKE, BIT(2) | BIT(3) | BIT(5), MMIO | MMIO_SBDS | RETBLEED),
1254+ VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS | RETBLEED),
1255+ VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED),
1256+ VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS | RETBLEED),
1257+ VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPINGS(0x1, 0x1), MMIO | RETBLEED),
12581258 VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS),
12591259 VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO),
12601260 VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPINGS(0x0, 0x0), MMIO | MMIO_SBDS),
@@ -1364,7 +1364,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) · 103 unmodified lines
13641364 !arch_cap_mmio_immune(ia32_cap))
13651365 setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
13661366
1367− if (cpu_matches(cpu_vuln_blacklist, RETBLEED))
1367+ if ((cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA)))
13681368 setup_force_cpu_bug(X86_BUG_RETBLEED);
13691369
13701370 if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))