[PATCH v3 31/35] x86/bugs: Add attack vector controls for bhi

From: David Kaplan
Date: Wed Jan 08 2025 - 15:31:58 EST


There are two BHI mitigations, one for SYSCALL and one for VMEXIT.
Split these up so they can be selected individually based on attack
vector.

Signed-off-by: David Kaplan <david.kaplan@xxxxxxx>
---
arch/x86/kernel/cpu/bugs.c | 38 ++++++++++++++++++++++++++------------
1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index c1b60ffa3218..57c762d86fca 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -1945,8 +1945,9 @@ static bool __init spec_ctrl_bhi_dis(void)
enum bhi_mitigations {
BHI_MITIGATION_OFF,
BHI_MITIGATION_AUTO,
- BHI_MITIGATION_ON,
- BHI_MITIGATION_VMEXIT_ONLY,
+ BHI_MITIGATION_FULL,
+ BHI_MITIGATION_VMEXIT,
+ BHI_MITIGATION_SYSCALL
};

static enum bhi_mitigations bhi_mitigation __ro_after_init =
@@ -1960,9 +1961,9 @@ static int __init spectre_bhi_parse_cmdline(char *str)
if (!strcmp(str, "off"))
bhi_mitigation = BHI_MITIGATION_OFF;
else if (!strcmp(str, "on"))
- bhi_mitigation = BHI_MITIGATION_ON;
+ bhi_mitigation = BHI_MITIGATION_FULL;
else if (!strcmp(str, "vmexit"))
- bhi_mitigation = BHI_MITIGATION_VMEXIT_ONLY;
+ bhi_mitigation = BHI_MITIGATION_VMEXIT;
else
pr_err("Ignoring unknown spectre_bhi option (%s)", str);

@@ -1975,8 +1976,17 @@ static void __init bhi_select_mitigation(void)
if (!boot_cpu_has(X86_BUG_BHI) || cpu_mitigations_off())
bhi_mitigation = BHI_MITIGATION_OFF;

- if (bhi_mitigation == BHI_MITIGATION_AUTO)
- bhi_mitigation = BHI_MITIGATION_ON;
+ if (bhi_mitigation == BHI_MITIGATION_AUTO) {
+ if (cpu_mitigate_attack_vector(CPU_MITIGATE_USER_KERNEL)) {
+ if (cpu_mitigate_attack_vector(CPU_MITIGATE_GUEST_HOST))
+ bhi_mitigation = BHI_MITIGATION_FULL;
+ else
+ bhi_mitigation = BHI_MITIGATION_SYSCALL;
+ } else if (cpu_mitigate_attack_vector(CPU_MITIGATE_GUEST_HOST))
+ bhi_mitigation = BHI_MITIGATION_VMEXIT;
+ else
+ bhi_mitigation = BHI_MITIGATION_OFF;
+ }
}

static void __init bhi_apply_mitigation(void)
@@ -1999,15 +2009,19 @@ static void __init bhi_apply_mitigation(void)
if (!IS_ENABLED(CONFIG_X86_64))
return;

- if (bhi_mitigation == BHI_MITIGATION_VMEXIT_ONLY) {
- pr_info("Spectre BHI mitigation: SW BHB clearing on VM exit only\n");
+ /* Mitigate KVM if guest->host protection is desired */
+ if (bhi_mitigation == BHI_MITIGATION_FULL ||
+ bhi_mitigation == BHI_MITIGATION_VMEXIT) {
setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
- return;
+ pr_info("Spectre BHI mitigation: SW BHB clearing on VM exit\n");
}

- pr_info("Spectre BHI mitigation: SW BHB clearing on syscall and VM exit\n");
- setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
- setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
+ /* Mitigate syscalls if user->kernel protection is desired */
+ if (bhi_mitigation == BHI_MITIGATION_FULL ||
+ bhi_mitigation == BHI_MITIGATION_SYSCALL) {
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
+ pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
+ }
}

static void __init spectre_v2_select_mitigation(void)
--
2.34.1