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
93#define MSR_IA32_ARCH_CAPABILITIES 0x0000010a93#define MSR_IA32_ARCH_CAPABILITIES 0x0000010a
94#define ARCH_CAP_RDCL_NO BIT(0) /* Not susceptible to Meltdown */94#define ARCH_CAP_RDCL_NO BIT(0) /* Not susceptible to Meltdown */
95#define ARCH_CAP_IBRS_ALL BIT(1) /* Enhanced IBRS support */95#define ARCH_CAP_IBRS_ALL BIT(1) /* Enhanced IBRS support */
96#define ARCH_CAP_RSBA BIT(2) /* RET may use alternative branch predictors */
96#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH BIT(3) /* Skip L1D flush on vmentry */97#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH BIT(3) /* Skip L1D flush on vmentry */
97#define ARCH_CAP_SSB_NO BIT(4) /*98#define ARCH_CAP_SSB_NO BIT(4) /*
98 * Not susceptible to Speculative Store Bypass99 * 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
790}790}
791early_param("nospectre_v1", nospectre_v1_cmdline);791early_param("nospectre_v1", nospectre_v1_cmdline);
792 792
793static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
794 SPECTRE_V2_NONE;
795
793#undef pr_fmt796#undef pr_fmt
794#define pr_fmt(fmt) "RETBleed: " fmt797#define pr_fmt(fmt) "RETBleed: " fmt
795 798
796enum retbleed_mitigation {799enum retbleed_mitigation {
797 RETBLEED_MITIGATION_NONE,800 RETBLEED_MITIGATION_NONE,
798 RETBLEED_MITIGATION_UNRET,801 RETBLEED_MITIGATION_UNRET,
802 RETBLEED_MITIGATION_IBRS,
803 RETBLEED_MITIGATION_EIBRS,
799};804};
800 805
801enum retbleed_mitigation_cmd {806enum retbleed_mitigation_cmd {
@@ -807,6 +812,8 @@ enum retbleed_mitigation_cmd { · 5 unmodified lines
807const char * const retbleed_strings[] = {812const char * const retbleed_strings[] = {
808 [RETBLEED_MITIGATION_NONE] = "Vulnerable",813 [RETBLEED_MITIGATION_NONE] = "Vulnerable",
809 [RETBLEED_MITIGATION_UNRET] = "Mitigation: untrained return thunk",814 [RETBLEED_MITIGATION_UNRET] = "Mitigation: untrained return thunk",
815 [RETBLEED_MITIGATION_IBRS] = "Mitigation: IBRS",
816 [RETBLEED_MITIGATION_EIBRS] = "Mitigation: Enhanced IBRS",
810};817};
811 818
812static enum retbleed_mitigation retbleed_mitigation __ro_after_init =819static enum retbleed_mitigation retbleed_mitigation __ro_after_init =
@@ -849,6 +856,7 @@ early_param("retbleed", retbleed_parse_cmdline); · 36 unmodified lines
849 856
850#define RETBLEED_UNTRAIN_MSG "WARNING: BTB untrained return thunk mitigation is only effective on AMD/Hygon!\n"857#define RETBLEED_UNTRAIN_MSG "WARNING: BTB untrained return thunk mitigation is only effective on AMD/Hygon!\n"
851#define RETBLEED_COMPILER_MSG "WARNING: kernel not compiled with RETPOLINE or -mfunction-return capable compiler!\n"858#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"
852 860
853static void __init retbleed_select_mitigation(void)861static void __init retbleed_select_mitigation(void)
854{862{
@@ -865,12 +873,15 @@ static void __init retbleed_select_mitigation(void) · 10 unmodified lines
865 873
866 case RETBLEED_CMD_AUTO:874 case RETBLEED_CMD_AUTO:
867 default:875 default:
868 if (!boot_cpu_has_bug(X86_BUG_RETBLEED))
869 break;
870
871 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||876 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
872 boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)877 boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
873 retbleed_mitigation = RETBLEED_MITIGATION_UNRET;878 retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
879
880 /*
881 * The Intel mitigation (IBRS) was already selected in
882 * spectre_v2_select_mitigation().
883 */
884
874 break;885 break;
875 }886 }
876 887
@@ -900,15 +911,31 @@ static void __init retbleed_select_mitigation(void) · 23 unmodified lines
900 break;911 break;
901 }912 }
902 913
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
903 pr_info("%s\n", retbleed_strings[retbleed_mitigation]);933 pr_info("%s\n", retbleed_strings[retbleed_mitigation]);
904}934}
905 935
906#undef pr_fmt936#undef pr_fmt
907#define pr_fmt(fmt) "Spectre V2 : " fmt937#define pr_fmt(fmt) "Spectre V2 : " fmt
908 938
909static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
910 SPECTRE_V2_NONE;
911
912static enum spectre_v2_user_mitigation spectre_v2_user_stibp __ro_after_init =939static enum spectre_v2_user_mitigation spectre_v2_user_stibp __ro_after_init =
913 SPECTRE_V2_USER_NONE;940 SPECTRE_V2_USER_NONE;
914static enum spectre_v2_user_mitigation spectre_v2_user_ibpb __ro_after_init =941static 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
1237 VULNBL_INTEL_STEPPINGS(BROADWELL_G, X86_STEPPING_ANY, SRBDS),1237 VULNBL_INTEL_STEPPINGS(BROADWELL_G, X86_STEPPING_ANY, SRBDS),
1238 VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO),1238 VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO),
1239 VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS),1239 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),
1241 VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS),1241 VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS),
1242 VULNBL_INTEL_STEPPINGS(SKYLAKE_X, BIT(3) | BIT(4) | BIT(6) |1242 VULNBL_INTEL_STEPPINGS(SKYLAKE_X, BIT(3) | BIT(4) | BIT(6) |
1243 BIT(7) | BIT(0xB), MMIO),1243 BIT(7) | BIT(0xB), MMIO | RETBLEED),
1244 VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPINGS(0x3, 0x3), SRBDS | MMIO),1244 VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPINGS(0x3, 0x3), SRBDS | MMIO | RETBLEED),
1245 VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, SRBDS),1245 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),
1247 VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPINGS(0x0, 0x8), SRBDS),1247 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),
1249 VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPINGS(0x0, 0x8), SRBDS),1249 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),
1251 VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPINGS(0x1, 0x1), MMIO),1251 VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPINGS(0x1, 0x1), MMIO),
1252 VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x4, 0x6), MMIO),1252 VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPINGS(0x4, 0x6), MMIO),
1253 VULNBL_INTEL_STEPPINGS(COMETLAKE, BIT(2) | BIT(3) | BIT(5), MMIO | MMIO_SBDS),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),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),1255 VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED),
1256 VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS),1256 VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS | RETBLEED),
1257 VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPINGS(0x1, 0x1), MMIO),1257 VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPINGS(0x1, 0x1), MMIO | RETBLEED),
1258 VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS),1258 VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS),
1259 VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO),1259 VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO),
1260 VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPINGS(0x0, 0x0), MMIO | MMIO_SBDS),1260 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
1364 !arch_cap_mmio_immune(ia32_cap))1364 !arch_cap_mmio_immune(ia32_cap))
1365 setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);1365 setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
1366 1366
1367 if (cpu_matches(cpu_vuln_blacklist, RETBLEED))1367 if ((cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA)))
1368 setup_force_cpu_bug(X86_BUG_RETBLEED);1368 setup_force_cpu_bug(X86_BUG_RETBLEED);
1369 1369
1370 if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))1370 if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))