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 | #define MSR_IA32_ARCH_CAPABILITIES 0x0000010a | 93 | #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 Bypass | 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 | early_param("nospectre_v1", nospectre_v1_cmdline); | 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 | #undef pr_fmt | 796 | #undef pr_fmt |
| 794 | #define pr_fmt(fmt) "RETBleed: " fmt | 797 | #define pr_fmt(fmt) "RETBleed: " fmt |
| 795 | 798 | ||
| 796 | enum retbleed_mitigation { | 799 | enum 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 | ||
| 801 | enum retbleed_mitigation_cmd { | 806 | enum retbleed_mitigation_cmd { |
| @@ -807,6 +812,8 @@ enum retbleed_mitigation_cmd { · 5 unmodified lines | |||
| 807 | const char * const retbleed_strings[] = { | 812 | const 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 | ||
| 812 | static enum retbleed_mitigation retbleed_mitigation __ro_after_init = | 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 | #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 | ||
| 853 | static void __init retbleed_select_mitigation(void) | 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 | 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_fmt | 936 | #undef pr_fmt |
| 907 | #define pr_fmt(fmt) "Spectre V2 : " fmt | 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 | static enum spectre_v2_user_mitigation spectre_v2_user_stibp __ro_after_init = | 939 | static enum spectre_v2_user_mitigation spectre_v2_user_stibp __ro_after_init = |
| 913 | SPECTRE_V2_USER_NONE; | 940 | SPECTRE_V2_USER_NONE; |
| 914 | static enum spectre_v2_user_mitigation spectre_v2_user_ibpb __ro_after_init = | 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 | 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)) |