|
| 1 | +x86/bhi: Add BHI mitigation knob |
| 2 | + |
| 3 | +jira LE-2015 |
| 4 | +cve CVE-2024-2201 |
| 5 | +Rebuild_History Non-Buildable kernel-5.14.0-427.42.1.el9_4 |
| 6 | +commit-author Pawan Gupta <pawan.kumar.gupta@linux.intel.com> |
| 7 | +commit ec9404e40e8f36421a2b66ecb76dc2209fe7f3ef |
| 8 | +Empty-Commit: Cherry-Pick Conflicts during history rebuild. |
| 9 | +Will be included in final tarball splat. Ref for failed cherry-pick at: |
| 10 | +ciq/ciq_backports/kernel-5.14.0-427.42.1.el9_4/ec9404e4.failed |
| 11 | + |
| 12 | +Branch history clearing software sequences and hardware control |
| 13 | +BHI_DIS_S were defined to mitigate Branch History Injection (BHI). |
| 14 | + |
| 15 | +Add cmdline spectre_bhi={on|off|auto} to control BHI mitigation: |
| 16 | + |
| 17 | + auto - Deploy the hardware mitigation BHI_DIS_S, if available. |
| 18 | + on - Deploy the hardware mitigation BHI_DIS_S, if available, |
| 19 | + otherwise deploy the software sequence at syscall entry and |
| 20 | + VMexit. |
| 21 | + off - Turn off BHI mitigation. |
| 22 | + |
| 23 | +The default is auto mode which does not deploy the software sequence |
| 24 | +mitigation. This is because of the hardening done in the syscall |
| 25 | +dispatch path, which is the likely target of BHI. |
| 26 | + |
| 27 | + Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> |
| 28 | + Signed-off-by: Daniel Sneddon <daniel.sneddon@linux.intel.com> |
| 29 | + Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| 30 | + Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> |
| 31 | + Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org> |
| 32 | + |
| 33 | +(cherry picked from commit ec9404e40e8f36421a2b66ecb76dc2209fe7f3ef) |
| 34 | + Signed-off-by: Jonathan Maple <jmaple@ciq.com> |
| 35 | + |
| 36 | +# Conflicts: |
| 37 | +# Documentation/admin-guide/kernel-parameters.txt |
| 38 | +# arch/x86/include/asm/cpufeatures.h |
| 39 | +diff --cc Documentation/admin-guide/kernel-parameters.txt |
| 40 | +index f74f25f00a14,2dbe60c1db22..000000000000 |
| 41 | +--- a/Documentation/admin-guide/kernel-parameters.txt |
| 42 | ++++ b/Documentation/admin-guide/kernel-parameters.txt |
| 43 | +@@@ -5722,7 -6063,18 +5722,22 @@@ |
| 44 | + sonypi.*= [HW] Sony Programmable I/O Control Device driver |
| 45 | + See Documentation/admin-guide/laptops/sonypi.rst |
| 46 | + |
| 47 | +++<<<<<<< HEAD |
| 48 | + + spectre_v2= [X86] Control mitigation of Spectre variant 2 |
| 49 | +++======= |
| 50 | ++ spectre_bhi= [X86] Control mitigation of Branch History Injection |
| 51 | ++ (BHI) vulnerability. Syscalls are hardened against BHI |
| 52 | ++ reglardless of this setting. This setting affects the |
| 53 | ++ deployment of the HW BHI control and the SW BHB |
| 54 | ++ clearing sequence. |
| 55 | ++ |
| 56 | ++ on - unconditionally enable. |
| 57 | ++ off - unconditionally disable. |
| 58 | ++ auto - (default) enable only if hardware mitigation |
| 59 | ++ control(BHI_DIS_S) is available. |
| 60 | ++ |
| 61 | ++ spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2 |
| 62 | +++>>>>>>> ec9404e40e8f (x86/bhi: Add BHI mitigation knob) |
| 63 | + (indirect branch speculation) vulnerability. |
| 64 | + The default operation protects the kernel from |
| 65 | + user space attacks. |
| 66 | +diff --cc arch/x86/include/asm/cpufeatures.h |
| 67 | +index 54d64f0e0199,a2ee9a00e4a7..000000000000 |
| 68 | +--- a/arch/x86/include/asm/cpufeatures.h |
| 69 | ++++ b/arch/x86/include/asm/cpufeatures.h |
| 70 | +@@@ -462,6 -466,9 +462,12 @@@ |
| 71 | + * Reuse free bits when adding new feature flags! |
| 72 | + */ |
| 73 | + #define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */ |
| 74 | +++<<<<<<< HEAD |
| 75 | +++======= |
| 76 | ++ #define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */ |
| 77 | ++ #define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */ |
| 78 | ++ #define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */ |
| 79 | +++>>>>>>> ec9404e40e8f (x86/bhi: Add BHI mitigation knob) |
| 80 | + |
| 81 | + /* |
| 82 | + * BUG word(s) |
| 83 | +diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst |
| 84 | +index 166facdabe9f..07931fc13d60 100644 |
| 85 | +--- a/Documentation/admin-guide/hw-vuln/spectre.rst |
| 86 | ++++ b/Documentation/admin-guide/hw-vuln/spectre.rst |
| 87 | +@@ -138,11 +138,10 @@ associated with the source address of the indirect branch. Specifically, |
| 88 | + the BHB might be shared across privilege levels even in the presence of |
| 89 | + Enhanced IBRS. |
| 90 | + |
| 91 | +-Currently the only known real-world BHB attack vector is via |
| 92 | +-unprivileged eBPF. Therefore, it's highly recommended to not enable |
| 93 | +-unprivileged eBPF, especially when eIBRS is used (without retpolines). |
| 94 | +-For a full mitigation against BHB attacks, it's recommended to use |
| 95 | +-retpolines (or eIBRS combined with retpolines). |
| 96 | ++Previously the only known real-world BHB attack vector was via unprivileged |
| 97 | ++eBPF. Further research has found attacks that don't require unprivileged eBPF. |
| 98 | ++For a full mitigation against BHB attacks it is recommended to set BHI_DIS_S or |
| 99 | ++use the BHB clearing sequence. |
| 100 | + |
| 101 | + Attack scenarios |
| 102 | + ---------------- |
| 103 | +@@ -430,6 +429,21 @@ The possible values in this file are: |
| 104 | + 'PBRSB-eIBRS: Not affected' CPU is not affected by PBRSB |
| 105 | + =========================== ======================================================= |
| 106 | + |
| 107 | ++ - Branch History Injection (BHI) protection status: |
| 108 | ++ |
| 109 | ++.. list-table:: |
| 110 | ++ |
| 111 | ++ * - BHI: Not affected |
| 112 | ++ - System is not affected |
| 113 | ++ * - BHI: Retpoline |
| 114 | ++ - System is protected by retpoline |
| 115 | ++ * - BHI: BHI_DIS_S |
| 116 | ++ - System is protected by BHI_DIS_S |
| 117 | ++ * - BHI: SW loop |
| 118 | ++ - System is protected by software clearing sequence |
| 119 | ++ * - BHI: Syscall hardening |
| 120 | ++ - Syscalls are hardened against BHI |
| 121 | ++ |
| 122 | + Full mitigation might require a microcode update from the CPU |
| 123 | + vendor. When the necessary microcode is not available, the kernel will |
| 124 | + report vulnerability. |
| 125 | +@@ -484,7 +498,11 @@ Spectre variant 2 |
| 126 | + |
| 127 | + Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at |
| 128 | + boot, by setting the IBRS bit, and they're automatically protected against |
| 129 | +- Spectre v2 variant attacks. |
| 130 | ++ some Spectre v2 variant attacks. The BHB can still influence the choice of |
| 131 | ++ indirect branch predictor entry, and although branch predictor entries are |
| 132 | ++ isolated between modes when eIBRS is enabled, the BHB itself is not isolated |
| 133 | ++ between modes. Systems which support BHI_DIS_S will set it to protect against |
| 134 | ++ BHI attacks. |
| 135 | + |
| 136 | + On Intel's enhanced IBRS systems, this includes cross-thread branch target |
| 137 | + injections on SMT systems (STIBP). In other words, Intel eIBRS enables |
| 138 | +@@ -638,6 +656,21 @@ kernel command line. |
| 139 | + spectre_v2=off. Spectre variant 1 mitigations |
| 140 | + cannot be disabled. |
| 141 | + |
| 142 | ++ spectre_bhi= |
| 143 | ++ |
| 144 | ++ [X86] Control mitigation of Branch History Injection |
| 145 | ++ (BHI) vulnerability. Syscalls are hardened against BHI |
| 146 | ++ regardless of this setting. This setting affects the deployment |
| 147 | ++ of the HW BHI control and the SW BHB clearing sequence. |
| 148 | ++ |
| 149 | ++ on |
| 150 | ++ unconditionally enable. |
| 151 | ++ off |
| 152 | ++ unconditionally disable. |
| 153 | ++ auto |
| 154 | ++ enable if hardware mitigation |
| 155 | ++ control(BHI_DIS_S) is available. |
| 156 | ++ |
| 157 | + For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt |
| 158 | + |
| 159 | + Mitigation selection guide |
| 160 | +* Unmerged path Documentation/admin-guide/kernel-parameters.txt |
| 161 | +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig |
| 162 | +index 2e3190218496..120e57812c00 100644 |
| 163 | +--- a/arch/x86/Kconfig |
| 164 | ++++ b/arch/x86/Kconfig |
| 165 | +@@ -2641,6 +2641,31 @@ config MITIGATION_RFDS |
| 166 | + stored in floating point, vector and integer registers. |
| 167 | + See also <file:Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst> |
| 168 | + |
| 169 | ++choice |
| 170 | ++ prompt "Clear branch history" |
| 171 | ++ depends on CPU_SUP_INTEL |
| 172 | ++ default SPECTRE_BHI_AUTO |
| 173 | ++ help |
| 174 | ++ Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks |
| 175 | ++ where the branch history buffer is poisoned to speculatively steer |
| 176 | ++ indirect branches. |
| 177 | ++ See <file:Documentation/admin-guide/hw-vuln/spectre.rst> |
| 178 | ++ |
| 179 | ++config SPECTRE_BHI_ON |
| 180 | ++ bool "on" |
| 181 | ++ help |
| 182 | ++ Equivalent to setting spectre_bhi=on command line parameter. |
| 183 | ++config SPECTRE_BHI_OFF |
| 184 | ++ bool "off" |
| 185 | ++ help |
| 186 | ++ Equivalent to setting spectre_bhi=off command line parameter. |
| 187 | ++config SPECTRE_BHI_AUTO |
| 188 | ++ bool "auto" |
| 189 | ++ help |
| 190 | ++ Equivalent to setting spectre_bhi=auto command line parameter. |
| 191 | ++ |
| 192 | ++endchoice |
| 193 | ++ |
| 194 | + endif |
| 195 | + |
| 196 | + config ARCH_HAS_ADD_PAGES |
| 197 | +* Unmerged path arch/x86/include/asm/cpufeatures.h |
| 198 | +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c |
| 199 | +index d1c0c8f6898b..d65ffa0e7bd2 100644 |
| 200 | +--- a/arch/x86/kernel/cpu/bugs.c |
| 201 | ++++ b/arch/x86/kernel/cpu/bugs.c |
| 202 | +@@ -1612,6 +1612,74 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_ |
| 203 | + dump_stack(); |
| 204 | + } |
| 205 | + |
| 206 | ++/* |
| 207 | ++ * Set BHI_DIS_S to prevent indirect branches in kernel to be influenced by |
| 208 | ++ * branch history in userspace. Not needed if BHI_NO is set. |
| 209 | ++ */ |
| 210 | ++static bool __init spec_ctrl_bhi_dis(void) |
| 211 | ++{ |
| 212 | ++ if (!boot_cpu_has(X86_FEATURE_BHI_CTRL)) |
| 213 | ++ return false; |
| 214 | ++ |
| 215 | ++ x86_spec_ctrl_base |= SPEC_CTRL_BHI_DIS_S; |
| 216 | ++ update_spec_ctrl(x86_spec_ctrl_base); |
| 217 | ++ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_HW); |
| 218 | ++ |
| 219 | ++ return true; |
| 220 | ++} |
| 221 | ++ |
| 222 | ++enum bhi_mitigations { |
| 223 | ++ BHI_MITIGATION_OFF, |
| 224 | ++ BHI_MITIGATION_ON, |
| 225 | ++ BHI_MITIGATION_AUTO, |
| 226 | ++}; |
| 227 | ++ |
| 228 | ++static enum bhi_mitigations bhi_mitigation __ro_after_init = |
| 229 | ++ IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON : |
| 230 | ++ IS_ENABLED(CONFIG_SPECTRE_BHI_OFF) ? BHI_MITIGATION_OFF : |
| 231 | ++ BHI_MITIGATION_AUTO; |
| 232 | ++ |
| 233 | ++static int __init spectre_bhi_parse_cmdline(char *str) |
| 234 | ++{ |
| 235 | ++ if (!str) |
| 236 | ++ return -EINVAL; |
| 237 | ++ |
| 238 | ++ if (!strcmp(str, "off")) |
| 239 | ++ bhi_mitigation = BHI_MITIGATION_OFF; |
| 240 | ++ else if (!strcmp(str, "on")) |
| 241 | ++ bhi_mitigation = BHI_MITIGATION_ON; |
| 242 | ++ else if (!strcmp(str, "auto")) |
| 243 | ++ bhi_mitigation = BHI_MITIGATION_AUTO; |
| 244 | ++ else |
| 245 | ++ pr_err("Ignoring unknown spectre_bhi option (%s)", str); |
| 246 | ++ |
| 247 | ++ return 0; |
| 248 | ++} |
| 249 | ++early_param("spectre_bhi", spectre_bhi_parse_cmdline); |
| 250 | ++ |
| 251 | ++static void __init bhi_select_mitigation(void) |
| 252 | ++{ |
| 253 | ++ if (bhi_mitigation == BHI_MITIGATION_OFF) |
| 254 | ++ return; |
| 255 | ++ |
| 256 | ++ /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */ |
| 257 | ++ if (cpu_feature_enabled(X86_FEATURE_RETPOLINE) && |
| 258 | ++ !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA)) |
| 259 | ++ return; |
| 260 | ++ |
| 261 | ++ if (spec_ctrl_bhi_dis()) |
| 262 | ++ return; |
| 263 | ++ |
| 264 | ++ if (!IS_ENABLED(CONFIG_X86_64)) |
| 265 | ++ return; |
| 266 | ++ |
| 267 | ++ if (bhi_mitigation == BHI_MITIGATION_AUTO) |
| 268 | ++ return; |
| 269 | ++ |
| 270 | ++ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP); |
| 271 | ++ pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n"); |
| 272 | ++} |
| 273 | ++ |
| 274 | + static void __init spectre_v2_select_mitigation(void) |
| 275 | + { |
| 276 | + enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); |
| 277 | +@@ -1723,6 +1791,9 @@ static void __init spectre_v2_select_mitigation(void) |
| 278 | + mode == SPECTRE_V2_RETPOLINE) |
| 279 | + spec_ctrl_disable_kernel_rrsba(); |
| 280 | + |
| 281 | ++ if (boot_cpu_has(X86_BUG_BHI)) |
| 282 | ++ bhi_select_mitigation(); |
| 283 | ++ |
| 284 | + spectre_v2_enabled = mode; |
| 285 | + pr_info("%s\n", spectre_v2_strings[mode]); |
| 286 | + |
| 287 | +@@ -2814,6 +2885,21 @@ static char *pbrsb_eibrs_state(void) |
| 288 | + } |
| 289 | + } |
| 290 | + |
| 291 | ++static const char * const spectre_bhi_state(void) |
| 292 | ++{ |
| 293 | ++ if (!boot_cpu_has_bug(X86_BUG_BHI)) |
| 294 | ++ return "; BHI: Not affected"; |
| 295 | ++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW)) |
| 296 | ++ return "; BHI: BHI_DIS_S"; |
| 297 | ++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) |
| 298 | ++ return "; BHI: SW loop"; |
| 299 | ++ else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && |
| 300 | ++ !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA)) |
| 301 | ++ return "; BHI: Retpoline"; |
| 302 | ++ |
| 303 | ++ return "; BHI: Vulnerable (Syscall hardening enabled)"; |
| 304 | ++} |
| 305 | ++ |
| 306 | + static ssize_t spectre_v2_show_state(char *buf) |
| 307 | + { |
| 308 | + if (spectre_v2_enabled == SPECTRE_V2_LFENCE) |
| 309 | +@@ -2826,13 +2912,15 @@ static ssize_t spectre_v2_show_state(char *buf) |
| 310 | + spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE) |
| 311 | + return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n"); |
| 312 | + |
| 313 | +- return sysfs_emit(buf, "%s%s%s%s%s%s%s\n", |
| 314 | ++ return sysfs_emit(buf, "%s%s%s%s%s%s%s%s\n", |
| 315 | + spectre_v2_strings[spectre_v2_enabled], |
| 316 | + ibpb_state(), |
| 317 | + boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? "; IBRS_FW" : "", |
| 318 | + stibp_state(), |
| 319 | + boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? "; RSB filling" : "", |
| 320 | + pbrsb_eibrs_state(), |
| 321 | ++ spectre_bhi_state(), |
| 322 | ++ /* this should always be at the end */ |
| 323 | + spectre_v2_module_string()); |
| 324 | + } |
| 325 | + |
0 commit comments