| From 548fe0e92fee2bd5072af8d04b55afb96512efb8 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| 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 @@ 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 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); |
| } |
| -- |
| 2.21.0 |
| |