Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'x86_bugs_srso' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86/srso fixes from Borislav Petkov:
"Add a mitigation for the speculative RAS (Return Address Stack)
overflow vulnerability on AMD processors.

In short, this is yet another issue where userspace poisons a
microarchitectural structure which can then be used to leak privileged
information through a side channel"

* tag 'x86_bugs_srso' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/srso: Tie SBPB bit setting to microcode patch detection
x86/srso: Add a forgotten NOENDBR annotation
x86/srso: Fix return thunks in generated code
x86/srso: Add IBPB on VMEXIT
x86/srso: Add IBPB
x86/srso: Add SRSO_NO support
x86/srso: Add IBPB_BRTYPE support
x86/srso: Add a Speculative RAS Overflow mitigation
x86/bugs: Increase the x86 bugs vector size to two u32s

+521 -16
+1
Documentation/admin-guide/hw-vuln/index.rst
··· 19 19 l1d_flush.rst 20 20 processor_mmio_stale_data.rst 21 21 cross-thread-rsb.rst 22 + srso
+133
Documentation/admin-guide/hw-vuln/srso.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Speculative Return Stack Overflow (SRSO) 4 + ======================================== 5 + 6 + This is a mitigation for the speculative return stack overflow (SRSO) 7 + vulnerability found on AMD processors. The mechanism is by now the well 8 + known scenario of poisoning CPU functional units - the Branch Target 9 + Buffer (BTB) and Return Address Predictor (RAP) in this case - and then 10 + tricking the elevated privilege domain (the kernel) into leaking 11 + sensitive data. 12 + 13 + AMD CPUs predict RET instructions using a Return Address Predictor (aka 14 + Return Address Stack/Return Stack Buffer). In some cases, a non-architectural 15 + CALL instruction (i.e., an instruction predicted to be a CALL but is 16 + not actually a CALL) can create an entry in the RAP which may be used 17 + to predict the target of a subsequent RET instruction. 18 + 19 + The specific circumstances that lead to this varies by microarchitecture 20 + but the concern is that an attacker can mis-train the CPU BTB to predict 21 + non-architectural CALL instructions in kernel space and use this to 22 + control the speculative target of a subsequent kernel RET, potentially 23 + leading to information disclosure via a speculative side-channel. 24 + 25 + The issue is tracked under CVE-2023-20569. 26 + 27 + Affected processors 28 + ------------------- 29 + 30 + AMD Zen, generations 1-4. That is, all families 0x17 and 0x19. Older 31 + processors have not been investigated. 32 + 33 + System information and options 34 + ------------------------------ 35 + 36 + First of all, it is required that the latest microcode be loaded for 37 + mitigations to be effective. 38 + 39 + The sysfs file showing SRSO mitigation status is: 40 + 41 + /sys/devices/system/cpu/vulnerabilities/spec_rstack_overflow 42 + 43 + The possible values in this file are: 44 + 45 + - 'Not affected' The processor is not vulnerable 46 + 47 + - 'Vulnerable: no microcode' The processor is vulnerable, no 48 + microcode extending IBPB functionality 49 + to address the vulnerability has been 50 + applied. 51 + 52 + - 'Mitigation: microcode' Extended IBPB functionality microcode 53 + patch has been applied. It does not 54 + address User->Kernel and Guest->Host 55 + transitions protection but it does 56 + address User->User and VM->VM attack 57 + vectors. 58 + 59 + (spec_rstack_overflow=microcode) 60 + 61 + - 'Mitigation: safe RET' Software-only mitigation. It complements 62 + the extended IBPB microcode patch 63 + functionality by addressing User->Kernel 64 + and Guest->Host transitions protection. 65 + 66 + Selected by default or by 67 + spec_rstack_overflow=safe-ret 68 + 69 + - 'Mitigation: IBPB' Similar protection as "safe RET" above 70 + but employs an IBPB barrier on privilege 71 + domain crossings (User->Kernel, 72 + Guest->Host). 73 + 74 + (spec_rstack_overflow=ibpb) 75 + 76 + - 'Mitigation: IBPB on VMEXIT' Mitigation addressing the cloud provider 77 + scenario - the Guest->Host transitions 78 + only. 79 + 80 + (spec_rstack_overflow=ibpb-vmexit) 81 + 82 + In order to exploit vulnerability, an attacker needs to: 83 + 84 + - gain local access on the machine 85 + 86 + - break kASLR 87 + 88 + - find gadgets in the running kernel in order to use them in the exploit 89 + 90 + - potentially create and pin an additional workload on the sibling 91 + thread, depending on the microarchitecture (not necessary on fam 0x19) 92 + 93 + - run the exploit 94 + 95 + Considering the performance implications of each mitigation type, the 96 + default one is 'Mitigation: safe RET' which should take care of most 97 + attack vectors, including the local User->Kernel one. 98 + 99 + As always, the user is advised to keep her/his system up-to-date by 100 + applying software updates regularly. 101 + 102 + The default setting will be reevaluated when needed and especially when 103 + new attack vectors appear. 104 + 105 + As one can surmise, 'Mitigation: safe RET' does come at the cost of some 106 + performance depending on the workload. If one trusts her/his userspace 107 + and does not want to suffer the performance impact, one can always 108 + disable the mitigation with spec_rstack_overflow=off. 109 + 110 + Similarly, 'Mitigation: IBPB' is another full mitigation type employing 111 + an indrect branch prediction barrier after having applied the required 112 + microcode patch for one's system. This mitigation comes also at 113 + a performance cost. 114 + 115 + Mitigation: safe RET 116 + -------------------- 117 + 118 + The mitigation works by ensuring all RET instructions speculate to 119 + a controlled location, similar to how speculation is controlled in the 120 + retpoline sequence. To accomplish this, the __x86_return_thunk forces 121 + the CPU to mispredict every function return using a 'safe return' 122 + sequence. 123 + 124 + To ensure the safety of this mitigation, the kernel must ensure that the 125 + safe return sequence is itself free from attacker interference. In Zen3 126 + and Zen4, this is accomplished by creating a BTB alias between the 127 + untraining function srso_untrain_ret_alias() and the safe return 128 + function srso_safe_ret_alias() which results in evicting a potentially 129 + poisoned BTB entry and using that safe one for all function returns. 130 + 131 + In older Zen1 and Zen2, this is accomplished using a reinterpretation 132 + technique similar to Retbleed one: srso_untrain_ret() and 133 + srso_safe_ret().
+11
Documentation/admin-guide/kernel-parameters.txt
··· 5875 5875 Not specifying this option is equivalent to 5876 5876 spectre_v2_user=auto. 5877 5877 5878 + spec_rstack_overflow= 5879 + [X86] Control RAS overflow mitigation on AMD Zen CPUs 5880 + 5881 + off - Disable mitigation 5882 + microcode - Enable microcode mitigation only 5883 + safe-ret - Enable sw-only safe RET mitigation (default) 5884 + ibpb - Enable mitigation by issuing IBPB on 5885 + kernel entry 5886 + ibpb-vmexit - Issue IBPB only on VMEXIT 5887 + (cloud-specific mitigation) 5888 + 5878 5889 spec_store_bypass_disable= 5879 5890 [HW] Control Speculative Store Bypass (SSB) Disable mitigation 5880 5891 (Speculative Store Bypass vulnerability)
+7
arch/x86/Kconfig
··· 2593 2593 This mitigates both spectre_v2 and retbleed at great cost to 2594 2594 performance. 2595 2595 2596 + config CPU_SRSO 2597 + bool "Mitigate speculative RAS overflow on AMD" 2598 + depends on CPU_SUP_AMD && X86_64 && RETHUNK 2599 + default y 2600 + help 2601 + Enable the SRSO mitigation needed on AMD Zen1-4 machines. 2602 + 2596 2603 config SLS 2597 2604 bool "Mitigate Straight-Line-Speculation" 2598 2605 depends on CC_HAS_SLS && X86_64
+11 -1
arch/x86/include/asm/cpufeatures.h
··· 14 14 * Defines x86 CPU feature bits 15 15 */ 16 16 #define NCAPINTS 21 /* N 32-bit words worth of info */ 17 - #define NBUGINTS 1 /* N 32-bit bug flags */ 17 + #define NBUGINTS 2 /* N 32-bit bug flags */ 18 18 19 19 /* 20 20 * Note: If the comment begins with a quoted string, that string is used ··· 309 309 #define X86_FEATURE_SMBA (11*32+21) /* "" Slow Memory Bandwidth Allocation */ 310 310 #define X86_FEATURE_BMEC (11*32+22) /* "" Bandwidth Monitoring Event Configuration */ 311 311 312 + #define X86_FEATURE_SRSO (11*32+24) /* "" AMD BTB untrain RETs */ 313 + #define X86_FEATURE_SRSO_ALIAS (11*32+25) /* "" AMD BTB untrain RETs through aliasing */ 314 + #define X86_FEATURE_IBPB_ON_VMEXIT (11*32+26) /* "" Issue an IBPB only on VMEXIT */ 315 + 312 316 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ 313 317 #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ 314 318 #define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ ··· 446 442 #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */ 447 443 #define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* "" SMM_CTL MSR is not present */ 448 444 445 + #define X86_FEATURE_SBPB (20*32+27) /* "" Selective Branch Prediction Barrier */ 446 + #define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */ 447 + #define X86_FEATURE_SRSO_NO (20*32+29) /* "" CPU is not affected by SRSO */ 448 + 449 449 /* 450 450 * BUG word(s) 451 451 */ ··· 492 484 #define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */ 493 485 #define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */ 494 486 487 + /* BUG word 2 */ 488 + #define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */ 495 489 #endif /* _ASM_X86_CPUFEATURES_H */
+1
arch/x86/include/asm/msr-index.h
··· 57 57 58 58 #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ 59 59 #define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */ 60 + #define PRED_CMD_SBPB BIT(7) /* Selective Branch Prediction Barrier */ 60 61 61 62 #define MSR_PPIN_CTL 0x0000004e 62 63 #define MSR_PPIN 0x0000004f
+18 -5
arch/x86/include/asm/nospec-branch.h
··· 211 211 * eventually turn into it's own annotation. 212 212 */ 213 213 .macro VALIDATE_UNRET_END 214 - #if defined(CONFIG_NOINSTR_VALIDATION) && defined(CONFIG_CPU_UNRET_ENTRY) 214 + #if defined(CONFIG_NOINSTR_VALIDATION) && \ 215 + (defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO)) 215 216 ANNOTATE_RETPOLINE_SAFE 216 217 nop 217 218 #endif ··· 290 289 */ 291 290 .macro UNTRAIN_RET 292 291 #if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \ 293 - defined(CONFIG_CALL_DEPTH_TRACKING) 292 + defined(CONFIG_CALL_DEPTH_TRACKING) || defined(CONFIG_CPU_SRSO) 294 293 VALIDATE_UNRET_END 295 294 ALTERNATIVE_3 "", \ 296 295 CALL_ZEN_UNTRAIN_RET, X86_FEATURE_UNRET, \ 297 296 "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \ 298 297 __stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH 298 + #endif 299 + 300 + #ifdef CONFIG_CPU_SRSO 301 + ALTERNATIVE_2 "", "call srso_untrain_ret", X86_FEATURE_SRSO, \ 302 + "call srso_untrain_ret_alias", X86_FEATURE_SRSO_ALIAS 299 303 #endif 300 304 .endm 301 305 ··· 312 306 CALL_ZEN_UNTRAIN_RET, X86_FEATURE_UNRET, \ 313 307 "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \ 314 308 __stringify(RESET_CALL_DEPTH_FROM_CALL), X86_FEATURE_CALL_DEPTH 309 + #endif 310 + 311 + #ifdef CONFIG_CPU_SRSO 312 + ALTERNATIVE_2 "", "call srso_untrain_ret", X86_FEATURE_SRSO, \ 313 + "call srso_untrain_ret_alias", X86_FEATURE_SRSO_ALIAS 315 314 #endif 316 315 .endm 317 316 ··· 343 332 344 333 extern void __x86_return_thunk(void); 345 334 extern void zen_untrain_ret(void); 335 + extern void srso_untrain_ret(void); 336 + extern void srso_untrain_ret_alias(void); 346 337 extern void entry_ibpb(void); 347 338 348 339 #ifdef CONFIG_CALL_THUNKS ··· 492 479 : "memory"); 493 480 } 494 481 482 + extern u64 x86_pred_cmd; 483 + 495 484 static inline void indirect_branch_prediction_barrier(void) 496 485 { 497 - u64 val = PRED_CMD_IBPB; 498 - 499 - alternative_msr_write(MSR_IA32_PRED_CMD, val, X86_FEATURE_USE_IBPB); 486 + alternative_msr_write(MSR_IA32_PRED_CMD, x86_pred_cmd, X86_FEATURE_USE_IBPB); 500 487 } 501 488 502 489 /* The Intel SPEC CTRL MSR base value cache */
+2
arch/x86/include/asm/processor.h
··· 682 682 #ifdef CONFIG_CPU_SUP_AMD 683 683 extern u32 amd_get_nodes_per_socket(void); 684 684 extern u32 amd_get_highest_perf(void); 685 + extern bool cpu_has_ibpb_brtype_microcode(void); 685 686 #else 686 687 static inline u32 amd_get_nodes_per_socket(void) { return 0; } 687 688 static inline u32 amd_get_highest_perf(void) { return 0; } 689 + static inline bool cpu_has_ibpb_brtype_microcode(void) { return false; } 688 690 #endif 689 691 690 692 extern unsigned long arch_align_stack(unsigned long sp);
+19
arch/x86/kernel/cpu/amd.c
··· 1290 1290 { 1291 1291 on_each_cpu(zenbleed_check_cpu, NULL, 1); 1292 1292 } 1293 + 1294 + bool cpu_has_ibpb_brtype_microcode(void) 1295 + { 1296 + switch (boot_cpu_data.x86) { 1297 + /* Zen1/2 IBPB flushes branch type predictions too. */ 1298 + case 0x17: 1299 + return boot_cpu_has(X86_FEATURE_AMD_IBPB); 1300 + case 0x19: 1301 + /* Poke the MSR bit on Zen3/4 to check its presence. */ 1302 + if (!wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) { 1303 + setup_force_cpu_cap(X86_FEATURE_SBPB); 1304 + return true; 1305 + } else { 1306 + return false; 1307 + } 1308 + default: 1309 + return false; 1310 + } 1311 + }
+179
arch/x86/kernel/cpu/bugs.c
··· 47 47 static void __init mmio_select_mitigation(void); 48 48 static void __init srbds_select_mitigation(void); 49 49 static void __init l1d_flush_select_mitigation(void); 50 + static void __init srso_select_mitigation(void); 50 51 51 52 /* The base value of the SPEC_CTRL MSR without task-specific bits set */ 52 53 u64 x86_spec_ctrl_base; ··· 56 55 /* The current value of the SPEC_CTRL MSR with task-specific bits set */ 57 56 DEFINE_PER_CPU(u64, x86_spec_ctrl_current); 58 57 EXPORT_SYMBOL_GPL(x86_spec_ctrl_current); 58 + 59 + u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB; 60 + EXPORT_SYMBOL_GPL(x86_pred_cmd); 59 61 60 62 static DEFINE_MUTEX(spec_ctrl_mutex); 61 63 ··· 164 160 md_clear_select_mitigation(); 165 161 srbds_select_mitigation(); 166 162 l1d_flush_select_mitigation(); 163 + srso_select_mitigation(); 167 164 } 168 165 169 166 /* ··· 2193 2188 early_param("l1tf", l1tf_cmdline); 2194 2189 2195 2190 #undef pr_fmt 2191 + #define pr_fmt(fmt) "Speculative Return Stack Overflow: " fmt 2192 + 2193 + enum srso_mitigation { 2194 + SRSO_MITIGATION_NONE, 2195 + SRSO_MITIGATION_MICROCODE, 2196 + SRSO_MITIGATION_SAFE_RET, 2197 + SRSO_MITIGATION_IBPB, 2198 + SRSO_MITIGATION_IBPB_ON_VMEXIT, 2199 + }; 2200 + 2201 + enum srso_mitigation_cmd { 2202 + SRSO_CMD_OFF, 2203 + SRSO_CMD_MICROCODE, 2204 + SRSO_CMD_SAFE_RET, 2205 + SRSO_CMD_IBPB, 2206 + SRSO_CMD_IBPB_ON_VMEXIT, 2207 + }; 2208 + 2209 + static const char * const srso_strings[] = { 2210 + [SRSO_MITIGATION_NONE] = "Vulnerable", 2211 + [SRSO_MITIGATION_MICROCODE] = "Mitigation: microcode", 2212 + [SRSO_MITIGATION_SAFE_RET] = "Mitigation: safe RET", 2213 + [SRSO_MITIGATION_IBPB] = "Mitigation: IBPB", 2214 + [SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only" 2215 + }; 2216 + 2217 + static enum srso_mitigation srso_mitigation __ro_after_init = SRSO_MITIGATION_NONE; 2218 + static enum srso_mitigation_cmd srso_cmd __ro_after_init = SRSO_CMD_SAFE_RET; 2219 + 2220 + static int __init srso_parse_cmdline(char *str) 2221 + { 2222 + if (!str) 2223 + return -EINVAL; 2224 + 2225 + if (!strcmp(str, "off")) 2226 + srso_cmd = SRSO_CMD_OFF; 2227 + else if (!strcmp(str, "microcode")) 2228 + srso_cmd = SRSO_CMD_MICROCODE; 2229 + else if (!strcmp(str, "safe-ret")) 2230 + srso_cmd = SRSO_CMD_SAFE_RET; 2231 + else if (!strcmp(str, "ibpb")) 2232 + srso_cmd = SRSO_CMD_IBPB; 2233 + else if (!strcmp(str, "ibpb-vmexit")) 2234 + srso_cmd = SRSO_CMD_IBPB_ON_VMEXIT; 2235 + else 2236 + pr_err("Ignoring unknown SRSO option (%s).", str); 2237 + 2238 + return 0; 2239 + } 2240 + early_param("spec_rstack_overflow", srso_parse_cmdline); 2241 + 2242 + #define SRSO_NOTICE "WARNING: See https://kernel.org/doc/html/latest/admin-guide/hw-vuln/srso.html for mitigation options." 2243 + 2244 + static void __init srso_select_mitigation(void) 2245 + { 2246 + bool has_microcode; 2247 + 2248 + if (!boot_cpu_has_bug(X86_BUG_SRSO) || cpu_mitigations_off()) 2249 + goto pred_cmd; 2250 + 2251 + /* 2252 + * The first check is for the kernel running as a guest in order 2253 + * for guests to verify whether IBPB is a viable mitigation. 2254 + */ 2255 + has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) || cpu_has_ibpb_brtype_microcode(); 2256 + if (!has_microcode) { 2257 + pr_warn("IBPB-extending microcode not applied!\n"); 2258 + pr_warn(SRSO_NOTICE); 2259 + } else { 2260 + /* 2261 + * Enable the synthetic (even if in a real CPUID leaf) 2262 + * flags for guests. 2263 + */ 2264 + setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE); 2265 + 2266 + /* 2267 + * Zen1/2 with SMT off aren't vulnerable after the right 2268 + * IBPB microcode has been applied. 2269 + */ 2270 + if ((boot_cpu_data.x86 < 0x19) && 2271 + (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) 2272 + setup_force_cpu_cap(X86_FEATURE_SRSO_NO); 2273 + } 2274 + 2275 + if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) { 2276 + if (has_microcode) { 2277 + pr_err("Retbleed IBPB mitigation enabled, using same for SRSO\n"); 2278 + srso_mitigation = SRSO_MITIGATION_IBPB; 2279 + goto pred_cmd; 2280 + } 2281 + } 2282 + 2283 + switch (srso_cmd) { 2284 + case SRSO_CMD_OFF: 2285 + return; 2286 + 2287 + case SRSO_CMD_MICROCODE: 2288 + if (has_microcode) { 2289 + srso_mitigation = SRSO_MITIGATION_MICROCODE; 2290 + pr_warn(SRSO_NOTICE); 2291 + } 2292 + break; 2293 + 2294 + case SRSO_CMD_SAFE_RET: 2295 + if (IS_ENABLED(CONFIG_CPU_SRSO)) { 2296 + /* 2297 + * Enable the return thunk for generated code 2298 + * like ftrace, static_call, etc. 2299 + */ 2300 + setup_force_cpu_cap(X86_FEATURE_RETHUNK); 2301 + 2302 + if (boot_cpu_data.x86 == 0x19) 2303 + setup_force_cpu_cap(X86_FEATURE_SRSO_ALIAS); 2304 + else 2305 + setup_force_cpu_cap(X86_FEATURE_SRSO); 2306 + srso_mitigation = SRSO_MITIGATION_SAFE_RET; 2307 + } else { 2308 + pr_err("WARNING: kernel not compiled with CPU_SRSO.\n"); 2309 + goto pred_cmd; 2310 + } 2311 + break; 2312 + 2313 + case SRSO_CMD_IBPB: 2314 + if (IS_ENABLED(CONFIG_CPU_IBPB_ENTRY)) { 2315 + if (has_microcode) { 2316 + setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); 2317 + srso_mitigation = SRSO_MITIGATION_IBPB; 2318 + } 2319 + } else { 2320 + pr_err("WARNING: kernel not compiled with CPU_IBPB_ENTRY.\n"); 2321 + goto pred_cmd; 2322 + } 2323 + break; 2324 + 2325 + case SRSO_CMD_IBPB_ON_VMEXIT: 2326 + if (IS_ENABLED(CONFIG_CPU_SRSO)) { 2327 + if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) { 2328 + setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); 2329 + srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT; 2330 + } 2331 + } else { 2332 + pr_err("WARNING: kernel not compiled with CPU_SRSO.\n"); 2333 + goto pred_cmd; 2334 + } 2335 + break; 2336 + 2337 + default: 2338 + break; 2339 + } 2340 + 2341 + pr_info("%s%s\n", srso_strings[srso_mitigation], (has_microcode ? "" : ", no microcode")); 2342 + 2343 + pred_cmd: 2344 + if ((boot_cpu_has(X86_FEATURE_SRSO_NO) || srso_cmd == SRSO_CMD_OFF) && 2345 + boot_cpu_has(X86_FEATURE_SBPB)) 2346 + x86_pred_cmd = PRED_CMD_SBPB; 2347 + } 2348 + 2349 + #undef pr_fmt 2196 2350 #define pr_fmt(fmt) fmt 2197 2351 2198 2352 #ifdef CONFIG_SYSFS ··· 2549 2385 return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]); 2550 2386 } 2551 2387 2388 + static ssize_t srso_show_state(char *buf) 2389 + { 2390 + return sysfs_emit(buf, "%s%s\n", 2391 + srso_strings[srso_mitigation], 2392 + (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode")); 2393 + } 2394 + 2552 2395 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, 2553 2396 char *buf, unsigned int bug) 2554 2397 { ··· 2604 2433 2605 2434 case X86_BUG_RETBLEED: 2606 2435 return retbleed_show_state(buf); 2436 + 2437 + case X86_BUG_SRSO: 2438 + return srso_show_state(buf); 2607 2439 2608 2440 default: 2609 2441 break; ··· 2671 2497 ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, char *buf) 2672 2498 { 2673 2499 return cpu_show_common(dev, attr, buf, X86_BUG_RETBLEED); 2500 + } 2501 + 2502 + ssize_t cpu_show_spec_rstack_overflow(struct device *dev, struct device_attribute *attr, char *buf) 2503 + { 2504 + return cpu_show_common(dev, attr, buf, X86_BUG_SRSO); 2674 2505 } 2675 2506 #endif
+9 -1
arch/x86/kernel/cpu/common.c
··· 1250 1250 #define RETBLEED BIT(3) 1251 1251 /* CPU is affected by SMT (cross-thread) return predictions */ 1252 1252 #define SMT_RSB BIT(4) 1253 + /* CPU is affected by SRSO */ 1254 + #define SRSO BIT(5) 1253 1255 1254 1256 static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { 1255 1257 VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS), ··· 1283 1281 1284 1282 VULNBL_AMD(0x15, RETBLEED), 1285 1283 VULNBL_AMD(0x16, RETBLEED), 1286 - VULNBL_AMD(0x17, RETBLEED | SMT_RSB), 1284 + VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO), 1287 1285 VULNBL_HYGON(0x18, RETBLEED | SMT_RSB), 1286 + VULNBL_AMD(0x19, SRSO), 1288 1287 {} 1289 1288 }; 1290 1289 ··· 1408 1405 1409 1406 if (cpu_matches(cpu_vuln_blacklist, SMT_RSB)) 1410 1407 setup_force_cpu_bug(X86_BUG_SMT_RSB); 1408 + 1409 + if (!cpu_has(c, X86_FEATURE_SRSO_NO)) { 1410 + if (cpu_matches(cpu_vuln_blacklist, SRSO)) 1411 + setup_force_cpu_bug(X86_BUG_SRSO); 1412 + } 1411 1413 1412 1414 if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) 1413 1415 return;
+27 -2
arch/x86/kernel/vmlinux.lds.S
··· 134 134 SOFTIRQENTRY_TEXT 135 135 #ifdef CONFIG_RETPOLINE 136 136 __indirect_thunk_start = .; 137 - *(.text.__x86.*) 137 + *(.text.__x86.indirect_thunk) 138 + *(.text.__x86.return_thunk) 138 139 __indirect_thunk_end = .; 139 140 #endif 140 141 STATIC_CALL_TEXT 141 142 142 143 ALIGN_ENTRY_TEXT_BEGIN 144 + #ifdef CONFIG_CPU_SRSO 145 + *(.text.__x86.rethunk_untrain) 146 + #endif 147 + 143 148 ENTRY_TEXT 149 + 150 + #ifdef CONFIG_CPU_SRSO 151 + /* 152 + * See the comment above srso_untrain_ret_alias()'s 153 + * definition. 154 + */ 155 + . = srso_untrain_ret_alias | (1 << 2) | (1 << 8) | (1 << 14) | (1 << 20); 156 + *(.text.__x86.rethunk_safe) 157 + #endif 144 158 ALIGN_ENTRY_TEXT_END 145 159 *(.gnu.warning) 146 160 ··· 523 509 #endif 524 510 525 511 #ifdef CONFIG_RETHUNK 526 - . = ASSERT((__x86_return_thunk & 0x3f) == 0, "__x86_return_thunk not cacheline-aligned"); 512 + . = ASSERT((__ret & 0x3f) == 0, "__ret not cacheline-aligned"); 513 + . = ASSERT((srso_safe_ret & 0x3f) == 0, "srso_safe_ret not cacheline-aligned"); 514 + #endif 515 + 516 + #ifdef CONFIG_CPU_SRSO 517 + /* 518 + * GNU ld cannot do XOR so do: (A | B) - (A & B) in order to compute the XOR 519 + * of the two function addresses: 520 + */ 521 + . = ASSERT(((srso_untrain_ret_alias | srso_safe_ret_alias) - 522 + (srso_untrain_ret_alias & srso_safe_ret_alias)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)), 523 + "SRSO function pair won't alias"); 527 524 #endif 528 525 529 526 #endif /* CONFIG_X86_64 */
+3
arch/x86/kvm/cpuid.c
··· 729 729 F(NULL_SEL_CLR_BASE) | F(AUTOIBRS) | 0 /* PrefetchCtlMsr */ 730 730 ); 731 731 732 + if (cpu_feature_enabled(X86_FEATURE_SRSO_NO)) 733 + kvm_cpu_cap_set(X86_FEATURE_SRSO_NO); 734 + 732 735 kvm_cpu_cap_init_kvm_defined(CPUID_8000_0022_EAX, 733 736 F(PERFMON_V2) 734 737 );
+3 -1
arch/x86/kvm/svm/svm.c
··· 1498 1498 1499 1499 if (sd->current_vmcb != svm->vmcb) { 1500 1500 sd->current_vmcb = svm->vmcb; 1501 - indirect_branch_prediction_barrier(); 1501 + 1502 + if (!cpu_feature_enabled(X86_FEATURE_IBPB_ON_VMEXIT)) 1503 + indirect_branch_prediction_barrier(); 1502 1504 } 1503 1505 if (kvm_vcpu_apicv_active(vcpu)) 1504 1506 avic_vcpu_load(vcpu, cpu);
+3
arch/x86/kvm/svm/vmenter.S
··· 224 224 */ 225 225 UNTRAIN_RET 226 226 227 + /* SRSO */ 228 + ALTERNATIVE "", "call entry_ibpb", X86_FEATURE_IBPB_ON_VMEXIT 229 + 227 230 /* 228 231 * Clear all general purpose registers except RSP and RAX to prevent 229 232 * speculative use of the guest's values, even those that are reloaded
+79 -4
arch/x86/lib/retpoline.S
··· 11 11 #include <asm/unwind_hints.h> 12 12 #include <asm/percpu.h> 13 13 #include <asm/frame.h> 14 + #include <asm/nops.h> 14 15 15 16 .section .text.__x86.indirect_thunk 16 17 ··· 132 131 */ 133 132 #ifdef CONFIG_RETHUNK 134 133 134 + /* 135 + * srso_untrain_ret_alias() and srso_safe_ret_alias() are placed at 136 + * special addresses: 137 + * 138 + * - srso_untrain_ret_alias() is 2M aligned 139 + * - srso_safe_ret_alias() is also in the same 2M page but bits 2, 8, 14 140 + * and 20 in its virtual address are set (while those bits in the 141 + * srso_untrain_ret_alias() function are cleared). 142 + * 143 + * This guarantees that those two addresses will alias in the branch 144 + * target buffer of Zen3/4 generations, leading to any potential 145 + * poisoned entries at that BTB slot to get evicted. 146 + * 147 + * As a result, srso_safe_ret_alias() becomes a safe return. 148 + */ 149 + #ifdef CONFIG_CPU_SRSO 150 + .section .text.__x86.rethunk_untrain 151 + 152 + SYM_START(srso_untrain_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) 153 + ANNOTATE_NOENDBR 154 + ASM_NOP2 155 + lfence 156 + jmp __x86_return_thunk 157 + SYM_FUNC_END(srso_untrain_ret_alias) 158 + __EXPORT_THUNK(srso_untrain_ret_alias) 159 + 160 + .section .text.__x86.rethunk_safe 161 + #endif 162 + 163 + /* Needs a definition for the __x86_return_thunk alternative below. */ 164 + SYM_START(srso_safe_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) 165 + #ifdef CONFIG_CPU_SRSO 166 + add $8, %_ASM_SP 167 + UNWIND_HINT_FUNC 168 + #endif 169 + ANNOTATE_UNRET_SAFE 170 + ret 171 + int3 172 + SYM_FUNC_END(srso_safe_ret_alias) 173 + 135 174 .section .text.__x86.return_thunk 136 175 137 176 /* ··· 184 143 * from re-poisioning the BTB prediction. 185 144 */ 186 145 .align 64 187 - .skip 64 - (__x86_return_thunk - zen_untrain_ret), 0xcc 146 + .skip 64 - (__ret - zen_untrain_ret), 0xcc 188 147 SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) 189 148 ANNOTATE_NOENDBR 190 149 /* ··· 216 175 * evicted, __x86_return_thunk will suffer Straight Line Speculation 217 176 * which will be contained safely by the INT3. 218 177 */ 219 - SYM_INNER_LABEL(__x86_return_thunk, SYM_L_GLOBAL) 178 + SYM_INNER_LABEL(__ret, SYM_L_GLOBAL) 220 179 ret 221 180 int3 222 - SYM_CODE_END(__x86_return_thunk) 181 + SYM_CODE_END(__ret) 223 182 224 183 /* 225 184 * Ensure the TEST decoding / BTB invalidation is complete. ··· 230 189 * Jump back and execute the RET in the middle of the TEST instruction. 231 190 * INT3 is for SLS protection. 232 191 */ 233 - jmp __x86_return_thunk 192 + jmp __ret 234 193 int3 235 194 SYM_FUNC_END(zen_untrain_ret) 236 195 __EXPORT_THUNK(zen_untrain_ret) 237 196 197 + /* 198 + * SRSO untraining sequence for Zen1/2, similar to zen_untrain_ret() 199 + * above. On kernel entry, srso_untrain_ret() is executed which is a 200 + * 201 + * movabs $0xccccccc308c48348,%rax 202 + * 203 + * and when the return thunk executes the inner label srso_safe_ret() 204 + * later, it is a stack manipulation and a RET which is mispredicted and 205 + * thus a "safe" one to use. 206 + */ 207 + .align 64 208 + .skip 64 - (srso_safe_ret - srso_untrain_ret), 0xcc 209 + SYM_START(srso_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) 210 + ANNOTATE_NOENDBR 211 + .byte 0x48, 0xb8 212 + 213 + SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL) 214 + add $8, %_ASM_SP 215 + ret 216 + int3 217 + int3 218 + int3 219 + lfence 220 + call srso_safe_ret 221 + int3 222 + SYM_CODE_END(srso_safe_ret) 223 + SYM_FUNC_END(srso_untrain_ret) 224 + __EXPORT_THUNK(srso_untrain_ret) 225 + 226 + SYM_FUNC_START(__x86_return_thunk) 227 + ALTERNATIVE_2 "jmp __ret", "call srso_safe_ret", X86_FEATURE_SRSO, \ 228 + "call srso_safe_ret_alias", X86_FEATURE_SRSO_ALIAS 229 + int3 230 + SYM_CODE_END(__x86_return_thunk) 238 231 EXPORT_SYMBOL(__x86_return_thunk) 239 232 240 233 #endif /* CONFIG_RETHUNK */
+8
drivers/base/cpu.c
··· 577 577 return sysfs_emit(buf, "Not affected\n"); 578 578 } 579 579 580 + ssize_t __weak cpu_show_spec_rstack_overflow(struct device *dev, 581 + struct device_attribute *attr, char *buf) 582 + { 583 + return sysfs_emit(buf, "Not affected\n"); 584 + } 585 + 580 586 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); 581 587 static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); 582 588 static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL); ··· 594 588 static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL); 595 589 static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL); 596 590 static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL); 591 + static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL); 597 592 598 593 static struct attribute *cpu_root_vulnerabilities_attrs[] = { 599 594 &dev_attr_meltdown.attr, ··· 608 601 &dev_attr_srbds.attr, 609 602 &dev_attr_mmio_stale_data.attr, 610 603 &dev_attr_retbleed.attr, 604 + &dev_attr_spec_rstack_overflow.attr, 611 605 NULL 612 606 }; 613 607
+2
include/linux/cpu.h
··· 70 70 char *buf); 71 71 extern ssize_t cpu_show_retbleed(struct device *dev, 72 72 struct device_attribute *attr, char *buf); 73 + extern ssize_t cpu_show_spec_rstack_overflow(struct device *dev, 74 + struct device_attribute *attr, char *buf); 73 75 74 76 extern __printf(4, 5) 75 77 struct device *cpu_device_create(struct device *parent, void *drvdata,
+1 -1
tools/arch/x86/include/asm/cpufeatures.h
··· 14 14 * Defines x86 CPU feature bits 15 15 */ 16 16 #define NCAPINTS 21 /* N 32-bit words worth of info */ 17 - #define NBUGINTS 1 /* N 32-bit bug flags */ 17 + #define NBUGINTS 2 /* N 32-bit bug flags */ 18 18 19 19 /* 20 20 * Note: If the comment begins with a quoted string, that string is used
+4 -1
tools/objtool/arch/x86/decode.c
··· 824 824 825 825 bool arch_is_rethunk(struct symbol *sym) 826 826 { 827 - return !strcmp(sym->name, "__x86_return_thunk"); 827 + return !strcmp(sym->name, "__x86_return_thunk") || 828 + !strcmp(sym->name, "srso_untrain_ret") || 829 + !strcmp(sym->name, "srso_safe_ret") || 830 + !strcmp(sym->name, "__ret"); 828 831 }