130 lines
4.8 KiB
Diff
130 lines
4.8 KiB
Diff
From 66260821438fb5c3e8b4b662c1ebd6ba0b077c09 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
Date: Wed, 20 Feb 2019 09:40:40 +0100
|
|
Subject: [PATCH 15/30] x86/speculation/mds: Add mitigation mode VMWERV
|
|
|
|
commit 22dd8365088b6403630b82423cf906491859b65e upstream
|
|
|
|
In virtualized environments it can happen that the host has the microcode
|
|
update which utilizes the VERW instruction to clear CPU buffers, but the
|
|
hypervisor is not yet updated to expose the X86_FEATURE_MD_CLEAR CPUID bit
|
|
to guests.
|
|
|
|
Introduce an internal mitigation mode VMWERV which enables the invocation
|
|
of the CPU buffer clearing even if X86_FEATURE_MD_CLEAR is not set. If the
|
|
system has no updated microcode this results in a pointless execution of
|
|
the VERW instruction wasting a few CPU cycles. If the microcode is updated,
|
|
but not exposed to a guest then the CPU buffers will be cleared.
|
|
|
|
That said: Virtual Machines Will Eventually Receive Vaccine
|
|
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Reviewed-by: Borislav Petkov <bp@suse.de>
|
|
Reviewed-by: Jon Masters <jcm@redhat.com>
|
|
Tested-by: Jon Masters <jcm@redhat.com>
|
|
---
|
|
Documentation/x86/mds.rst | 27 +++++++++++++++++++++++++++
|
|
arch/x86/include/asm/processor.h | 1 +
|
|
arch/x86/kernel/cpu/bugs.c | 18 ++++++++++++------
|
|
3 files changed, 40 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/Documentation/x86/mds.rst b/Documentation/x86/mds.rst
|
|
index 87ce8ac9f36e..3d6f943f1afb 100644
|
|
--- a/Documentation/x86/mds.rst
|
|
+++ b/Documentation/x86/mds.rst
|
|
@@ -93,11 +93,38 @@ enters a C-state.
|
|
The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state
|
|
(idle) transitions.
|
|
|
|
+As a special quirk to address virtualization scenarios where the host has
|
|
+the microcode updated, but the hypervisor does not (yet) expose the
|
|
+MD_CLEAR CPUID bit to guests, the kernel issues the VERW instruction in the
|
|
+hope that it might actually clear the buffers. The state is reflected
|
|
+accordingly.
|
|
+
|
|
According to current knowledge additional mitigations inside the kernel
|
|
itself are not required because the necessary gadgets to expose the leaked
|
|
data cannot be controlled in a way which allows exploitation from malicious
|
|
user space or VM guests.
|
|
|
|
+Kernel internal mitigation modes
|
|
+--------------------------------
|
|
+
|
|
+ ======= ============================================================
|
|
+ off Mitigation is disabled. Either the CPU is not affected or
|
|
+ mds=off is supplied on the kernel command line
|
|
+
|
|
+ full Mitigation is eanbled. CPU is affected and MD_CLEAR is
|
|
+ advertised in CPUID.
|
|
+
|
|
+ vmwerv Mitigation is enabled. CPU is affected and MD_CLEAR is not
|
|
+ advertised in CPUID. That is mainly for virtualization
|
|
+ scenarios where the host has the updated microcode but the
|
|
+ hypervisor does not expose MD_CLEAR in CPUID. It's a best
|
|
+ effort approach without guarantee.
|
|
+ ======= ============================================================
|
|
+
|
|
+If the CPU is affected and mds=off is not supplied on the kernel command
|
|
+line then the kernel selects the appropriate mitigation mode depending on
|
|
+the availability of the MD_CLEAR CPUID bit.
|
|
+
|
|
Mitigation points
|
|
-----------------
|
|
|
|
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
|
|
index 5e9f953face0..b54f25697beb 100644
|
|
--- a/arch/x86/include/asm/processor.h
|
|
+++ b/arch/x86/include/asm/processor.h
|
|
@@ -1000,6 +1000,7 @@ extern enum l1tf_mitigations l1tf_mitigation;
|
|
enum mds_mitigations {
|
|
MDS_MITIGATION_OFF,
|
|
MDS_MITIGATION_FULL,
|
|
+ MDS_MITIGATION_VMWERV,
|
|
};
|
|
|
|
#endif /* _ASM_X86_PROCESSOR_H */
|
|
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
|
|
index 50b7d2a980e8..053d71a3b9cc 100644
|
|
--- a/arch/x86/kernel/cpu/bugs.c
|
|
+++ b/arch/x86/kernel/cpu/bugs.c
|
|
@@ -222,7 +222,8 @@ static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_FULL
|
|
|
|
static const char * const mds_strings[] = {
|
|
[MDS_MITIGATION_OFF] = "Vulnerable",
|
|
- [MDS_MITIGATION_FULL] = "Mitigation: Clear CPU buffers"
|
|
+ [MDS_MITIGATION_FULL] = "Mitigation: Clear CPU buffers",
|
|
+ [MDS_MITIGATION_VMWERV] = "Vulnerable: Clear CPU buffers attempted, no microcode",
|
|
};
|
|
|
|
static void __init mds_select_mitigation(void)
|
|
@@ -233,10 +234,9 @@ static void __init mds_select_mitigation(void)
|
|
}
|
|
|
|
if (mds_mitigation == MDS_MITIGATION_FULL) {
|
|
- if (boot_cpu_has(X86_FEATURE_MD_CLEAR))
|
|
- static_branch_enable(&mds_user_clear);
|
|
- else
|
|
- mds_mitigation = MDS_MITIGATION_OFF;
|
|
+ if (!boot_cpu_has(X86_FEATURE_MD_CLEAR))
|
|
+ mds_mitigation = MDS_MITIGATION_VMWERV;
|
|
+ static_branch_enable(&mds_user_clear);
|
|
}
|
|
pr_info("%s\n", mds_strings[mds_mitigation]);
|
|
}
|
|
@@ -690,8 +690,14 @@ void arch_smt_update(void)
|
|
break;
|
|
}
|
|
|
|
- if (mds_mitigation == MDS_MITIGATION_FULL)
|
|
+ switch (mds_mitigation) {
|
|
+ case MDS_MITIGATION_FULL:
|
|
+ case MDS_MITIGATION_VMWERV:
|
|
update_mds_branch_idle();
|
|
+ break;
|
|
+ case MDS_MITIGATION_OFF:
|
|
+ break;
|
|
+ }
|
|
|
|
mutex_unlock(&spec_ctrl_mutex);
|
|
}
|