summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/x86/mds.rst27
-rw-r--r--arch/x86/include/asm/processor.h1
-rw-r--r--arch/x86/kernel/cpu/bugs.c18
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 @@ The kernel provides a function to invoke the buffer clearing:
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 e8718987c8f5..155e49fc7010 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -877,6 +877,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 fe374b25f3a6..1d6b7e9f0411 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -221,7 +221,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)
@@ -232,10 +233,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]);
}
@@ -698,8 +698,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);
}