diff options
Diffstat (limited to 'arch/x86/kernel/cpu/bugs.c')
| -rw-r--r-- | arch/x86/kernel/cpu/bugs.c | 86 | 
1 files changed, 63 insertions, 23 deletions
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 6761668100b9..9f7e751b91df 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1335,6 +1335,53 @@ static void __init spec_ctrl_disable_kernel_rrsba(void)  	}  } +static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode) +{ +	/* +	 * Similar to context switches, there are two types of RSB attacks +	 * after VM exit: +	 * +	 * 1) RSB underflow +	 * +	 * 2) Poisoned RSB entry +	 * +	 * When retpoline is enabled, both are mitigated by filling/clearing +	 * the RSB. +	 * +	 * When IBRS is enabled, while #1 would be mitigated by the IBRS branch +	 * prediction isolation protections, RSB still needs to be cleared +	 * because of #2.  Note that SMEP provides no protection here, unlike +	 * user-space-poisoned RSB entries. +	 * +	 * eIBRS should protect against RSB poisoning, but if the EIBRS_PBRSB +	 * bug is present then a LITE version of RSB protection is required, +	 * just a single call needs to retire before a RET is executed. +	 */ +	switch (mode) { +	case SPECTRE_V2_NONE: +		return; + +	case SPECTRE_V2_EIBRS_LFENCE: +	case SPECTRE_V2_EIBRS: +		if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) { +			setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT_LITE); +			pr_info("Spectre v2 / PBRSB-eIBRS: Retire a single CALL on VMEXIT\n"); +		} +		return; + +	case SPECTRE_V2_EIBRS_RETPOLINE: +	case SPECTRE_V2_RETPOLINE: +	case SPECTRE_V2_LFENCE: +	case SPECTRE_V2_IBRS: +		setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT); +		pr_info("Spectre v2 / SpectreRSB : Filling RSB on VMEXIT\n"); +		return; +	} + +	pr_warn_once("Unknown Spectre v2 mode, disabling RSB mitigation at VM exit"); +	dump_stack(); +} +  static void __init spectre_v2_select_mitigation(void)  {  	enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); @@ -1485,28 +1532,7 @@ static void __init spectre_v2_select_mitigation(void)  	setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);  	pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n"); -	/* -	 * Similar to context switches, there are two types of RSB attacks -	 * after vmexit: -	 * -	 * 1) RSB underflow -	 * -	 * 2) Poisoned RSB entry -	 * -	 * When retpoline is enabled, both are mitigated by filling/clearing -	 * the RSB. -	 * -	 * When IBRS is enabled, while #1 would be mitigated by the IBRS branch -	 * prediction isolation protections, RSB still needs to be cleared -	 * because of #2.  Note that SMEP provides no protection here, unlike -	 * user-space-poisoned RSB entries. -	 * -	 * eIBRS, on the other hand, has RSB-poisoning protections, so it -	 * doesn't need RSB clearing after vmexit. -	 */ -	if (boot_cpu_has(X86_FEATURE_RETPOLINE) || -	    boot_cpu_has(X86_FEATURE_KERNEL_IBRS)) -		setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT); +	spectre_v2_determine_rsb_fill_type_at_vmexit(mode);  	/*  	 * Retpoline protects the kernel, but doesn't protect firmware.  IBRS @@ -2292,6 +2318,19 @@ static char *ibpb_state(void)  	return "";  } +static char *pbrsb_eibrs_state(void) +{ +	if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) { +		if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) || +		    boot_cpu_has(X86_FEATURE_RSB_VMEXIT)) +			return ", PBRSB-eIBRS: SW sequence"; +		else +			return ", PBRSB-eIBRS: Vulnerable"; +	} else { +		return ", PBRSB-eIBRS: Not affected"; +	} +} +  static ssize_t spectre_v2_show_state(char *buf)  {  	if (spectre_v2_enabled == SPECTRE_V2_LFENCE) @@ -2304,12 +2343,13 @@ static ssize_t spectre_v2_show_state(char *buf)  	    spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)  		return sprintf(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n"); -	return sprintf(buf, "%s%s%s%s%s%s\n", +	return sprintf(buf, "%s%s%s%s%s%s%s\n",  		       spectre_v2_strings[spectre_v2_enabled],  		       ibpb_state(),  		       boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",  		       stibp_state(),  		       boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "", +		       pbrsb_eibrs_state(),  		       spectre_v2_module_string());  }  |