Skylake suffers from RSB underflow speculation issues; report this vulnerability and it's mitigation (spectre_v2=ibrs). [jpoimboe: cleanups, eibrs]
Unified · Split
| @@ -93,6 +93,7 @@ · 92 unmodified lines | ||
| 93 | 93 | #define MSR_IA32_ARCH_CAPABILITIES 0x0000010a |
| 94 | 94 | #define ARCH_CAP_RDCL_NO BIT(0) /* Not susceptible to Meltdown */ |
| 95 | 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 | 97 | #define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH BIT(3) /* Skip L1D flush on vmentry */ |
| 97 | 98 | #define ARCH_CAP_SSB_NO BIT(4) /* |
| 98 | 99 | * Not susceptible to Speculative Store Bypass |
| @@ -790,12 +790,17 @@ static int __init nospectre_v1_cmdline(char *str) · 789 unmodified lines | ||
| 790 | 790 | } |
| 791 | 791 | early_param("nospectre_v1", nospectre_v1_cmdline); |
| 792 | 792 | |
| 793 | +static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init = | |
| 794 | + SPECTRE_V2_NONE; | |
| 795 | + | |
| 793 | 796 | #undef pr_fmt |
| 794 | 797 | #define pr_fmt(fmt) "RETBleed: " fmt |
| 795 | 798 | |
| 796 | 799 | enum retbleed_mitigation { |
| 797 | 800 | RETBLEED_MITIGATION_NONE, |
| 798 | 801 | RETBLEED_MITIGATION_UNRET, |
| 802 | + RETBLEED_MITIGATION_IBRS, | |
| 803 | + RETBLEED_MITIGATION_EIBRS, | |
| 799 | 804 | }; |
| 800 | 805 | |
| 801 | 806 | enum retbleed_mitigation_cmd { |
| @@ -807,6 +812,8 @@ enum retbleed_mitigation_cmd { · 5 unmodified lines | ||
| 807 | 812 | const char * const retbleed_strings[] = { |
| 808 | 813 | [RETBLEED_MITIGATION_NONE] = "Vulnerable", |
| 809 | 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 | |
| 812 | 819 | static enum retbleed_mitigation retbleed_mitigation __ro_after_init = |
| @@ -849,6 +856,7 @@ early_param("retbleed", retbleed_parse_cmdline); · 36 unmodified lines | ||
| 849 | 856 | |
| 850 | 857 | #define RETBLEED_UNTRAIN_MSG "WARNING: BTB untrained return thunk mitigation is only effective on AMD/Hygon!\n" |
| 851 | 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 | |
| 853 | 861 | static 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 | 874 | case RETBLEED_CMD_AUTO: |
| 867 | 875 | default: |
| 868 | − if (!boot_cpu_has_bug(X86_BUG_RETBLEED)) | |
| 869 | − break; | |
| 870 | − | |
| 871 | 876 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || |
| 872 | 877 | boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) |
| 873 | 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 | 885 | break; |
| 875 | 886 | } |
| 876 | 887 | |
| @@ -900,15 +911,31 @@ static void __init retbleed_select_mitigation(void) · 23 unmodified lines | ||
| 900 | 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 | 933 | pr_info("%s\n", retbleed_strings[retbleed_mitigation]); |
| 904 | 934 | } |
| 905 | 935 | |
| 906 | 936 | #undef pr_fmt |
| 907 | 937 | #define pr_fmt(fmt) "Spectre V2 : " fmt |
| 908 | 938 | |
| 909 | −static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init = | |
| 910 | − SPECTRE_V2_NONE; | |
| 911 | − | |
| 912 | 939 | static enum spectre_v2_user_mitigation spectre_v2_user_stibp __ro_after_init = |
| 913 | 940 | SPECTRE_V2_USER_NONE; |
| 914 | 941 | static enum spectre_v2_user_mitigation spectre_v2_user_ibpb __ro_after_init = |
| @@ -1237,24 +1237,24 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { · 1236 unmodified lines | ||
| 1237 | 1237 | VULNBL_INTEL_STEPPINGS(BROADWELL_G, X86_STEPPING_ANY, SRBDS), |
| 1238 | 1238 | VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO), |
| 1239 | 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 | 1241 | VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS), |
| 1242 | 1242 | 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), | |
| 1245 | 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 | 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 | 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 | 1251 | VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPINGS(0x1, 0x1), MMIO), |
| 1252 | 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), | |
| 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), | |
| 1258 | 1258 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPINGS(0x1, 0x1), MMIO | MMIO_SBDS), |
| 1259 | 1259 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO), |
| 1260 | 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 | 1364 | !arch_cap_mmio_immune(ia32_cap)) |
| 1365 | 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 | 1368 | setup_force_cpu_bug(X86_BUG_RETBLEED); |
| 1369 | 1369 | |
| 1370 | 1370 | if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) |