| From a14bad2aed5c0c7905c397054f138cfb340daca3 Mon Sep 17 00:00:00 2001 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Mon, 18 Feb 2019 23:13:06 +0100 |
| Subject: [PATCH 09/30] x86/speculation/mds: Add mds_clear_cpu_buffers() |
| |
| commit 6a9e529272517755904b7afa639f6db59ddb793e upstream |
| |
| The Microarchitectural Data Sampling (MDS) vulernabilities are mitigated by |
| clearing the affected CPU buffers. The mechanism for clearing the buffers |
| uses the unused and obsolete VERW instruction in combination with a |
| microcode update which triggers a CPU buffer clear when VERW is executed. |
| |
| Provide a inline function with the assembly magic. The argument of the VERW |
| instruction must be a memory operand as documented: |
| |
| "MD_CLEAR enumerates that the memory-operand variant of VERW (for |
| example, VERW m16) has been extended to also overwrite buffers affected |
| by MDS. This buffer overwriting functionality is not guaranteed for the |
| register operand variant of VERW." |
| |
| Documentation also recommends to use a writable data segment selector: |
| |
| "The buffer overwriting occurs regardless of the result of the VERW |
| permission check, as well as when the selector is null or causes a |
| descriptor load segment violation. However, for lowest latency we |
| recommend using a selector that indicates a valid writable data |
| segment." |
| |
| Add x86 specific documentation about MDS and the internal workings of the |
| mitigation. |
| |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Reviewed-by: Borislav Petkov <bp@suse.de> |
| Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Reviewed-by: Frederic Weisbecker <frederic@kernel.org> |
| Reviewed-by: Jon Masters <jcm@redhat.com> |
| Tested-by: Jon Masters <jcm@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| Documentation/index.rst | 1 + |
| Documentation/x86/conf.py | 10 +++ |
| Documentation/x86/index.rst | 8 +++ |
| Documentation/x86/mds.rst | 99 ++++++++++++++++++++++++++++ |
| arch/x86/include/asm/nospec-branch.h | 25 +++++++ |
| 5 files changed, 143 insertions(+) |
| create mode 100644 Documentation/x86/conf.py |
| create mode 100644 Documentation/x86/index.rst |
| create mode 100644 Documentation/x86/mds.rst |
| |
| diff --git a/Documentation/index.rst b/Documentation/index.rst |
| index 5db7e87c7cb1..1cdc139adb40 100644 |
| --- a/Documentation/index.rst |
| +++ b/Documentation/index.rst |
| @@ -104,6 +104,7 @@ implementation. |
| :maxdepth: 2 |
| |
| sh/index |
| + x86/index |
| |
| Filesystem Documentation |
| ------------------------ |
| diff --git a/Documentation/x86/conf.py b/Documentation/x86/conf.py |
| new file mode 100644 |
| index 000000000000..33c5c3142e20 |
| --- /dev/null |
| +++ b/Documentation/x86/conf.py |
| @@ -0,0 +1,10 @@ |
| +# -*- coding: utf-8; mode: python -*- |
| + |
| +project = "X86 architecture specific documentation" |
| + |
| +tags.add("subproject") |
| + |
| +latex_documents = [ |
| + ('index', 'x86.tex', project, |
| + 'The kernel development community', 'manual'), |
| +] |
| diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst |
| new file mode 100644 |
| index 000000000000..ef389dcf1b1d |
| --- /dev/null |
| +++ b/Documentation/x86/index.rst |
| @@ -0,0 +1,8 @@ |
| +========================== |
| +x86 architecture specifics |
| +========================== |
| + |
| +.. toctree:: |
| + :maxdepth: 1 |
| + |
| + mds |
| diff --git a/Documentation/x86/mds.rst b/Documentation/x86/mds.rst |
| new file mode 100644 |
| index 000000000000..1096738d50f2 |
| --- /dev/null |
| +++ b/Documentation/x86/mds.rst |
| @@ -0,0 +1,99 @@ |
| +Microarchitectural Data Sampling (MDS) mitigation |
| +================================================= |
| + |
| +.. _mds: |
| + |
| +Overview |
| +-------- |
| + |
| +Microarchitectural Data Sampling (MDS) is a family of side channel attacks |
| +on internal buffers in Intel CPUs. The variants are: |
| + |
| + - Microarchitectural Store Buffer Data Sampling (MSBDS) (CVE-2018-12126) |
| + - Microarchitectural Fill Buffer Data Sampling (MFBDS) (CVE-2018-12130) |
| + - Microarchitectural Load Port Data Sampling (MLPDS) (CVE-2018-12127) |
| + |
| +MSBDS leaks Store Buffer Entries which can be speculatively forwarded to a |
| +dependent load (store-to-load forwarding) as an optimization. The forward |
| +can also happen to a faulting or assisting load operation for a different |
| +memory address, which can be exploited under certain conditions. Store |
| +buffers are partitioned between Hyper-Threads so cross thread forwarding is |
| +not possible. But if a thread enters or exits a sleep state the store |
| +buffer is repartitioned which can expose data from one thread to the other. |
| + |
| +MFBDS leaks Fill Buffer Entries. Fill buffers are used internally to manage |
| +L1 miss situations and to hold data which is returned or sent in response |
| +to a memory or I/O operation. Fill buffers can forward data to a load |
| +operation and also write data to the cache. When the fill buffer is |
| +deallocated it can retain the stale data of the preceding operations which |
| +can then be forwarded to a faulting or assisting load operation, which can |
| +be exploited under certain conditions. Fill buffers are shared between |
| +Hyper-Threads so cross thread leakage is possible. |
| + |
| +MLPDS leaks Load Port Data. Load ports are used to perform load operations |
| +from memory or I/O. The received data is then forwarded to the register |
| +file or a subsequent operation. In some implementations the Load Port can |
| +contain stale data from a previous operation which can be forwarded to |
| +faulting or assisting loads under certain conditions, which again can be |
| +exploited eventually. Load ports are shared between Hyper-Threads so cross |
| +thread leakage is possible. |
| + |
| + |
| +Exposure assumptions |
| +-------------------- |
| + |
| +It is assumed that attack code resides in user space or in a guest with one |
| +exception. The rationale behind this assumption is that the code construct |
| +needed for exploiting MDS requires: |
| + |
| + - to control the load to trigger a fault or assist |
| + |
| + - to have a disclosure gadget which exposes the speculatively accessed |
| + data for consumption through a side channel. |
| + |
| + - to control the pointer through which the disclosure gadget exposes the |
| + data |
| + |
| +The existence of such a construct in the kernel cannot be excluded with |
| +100% certainty, but the complexity involved makes it extremly unlikely. |
| + |
| +There is one exception, which is untrusted BPF. The functionality of |
| +untrusted BPF is limited, but it needs to be thoroughly investigated |
| +whether it can be used to create such a construct. |
| + |
| + |
| +Mitigation strategy |
| +------------------- |
| + |
| +All variants have the same mitigation strategy at least for the single CPU |
| +thread case (SMT off): Force the CPU to clear the affected buffers. |
| + |
| +This is achieved by using the otherwise unused and obsolete VERW |
| +instruction in combination with a microcode update. The microcode clears |
| +the affected CPU buffers when the VERW instruction is executed. |
| + |
| +For virtualization there are two ways to achieve CPU buffer |
| +clearing. Either the modified VERW instruction or via the L1D Flush |
| +command. The latter is issued when L1TF mitigation is enabled so the extra |
| +VERW can be avoided. If the CPU is not affected by L1TF then VERW needs to |
| +be issued. |
| + |
| +If the VERW instruction with the supplied segment selector argument is |
| +executed on a CPU without the microcode update there is no side effect |
| +other than a small number of pointlessly wasted CPU cycles. |
| + |
| +This does not protect against cross Hyper-Thread attacks except for MSBDS |
| +which is only exploitable cross Hyper-thread when one of the Hyper-Threads |
| +enters a C-state. |
| + |
| +The kernel provides a function to invoke the buffer clearing: |
| + |
| + mds_clear_cpu_buffers() |
| + |
| +The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state |
| +(idle) transitions. |
| + |
| +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. |
| diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h |
| index 032b6009baab..c022732e2cf9 100644 |
| --- a/arch/x86/include/asm/nospec-branch.h |
| +++ b/arch/x86/include/asm/nospec-branch.h |
| @@ -317,6 +317,31 @@ DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp); |
| DECLARE_STATIC_KEY_FALSE(switch_mm_cond_ibpb); |
| DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb); |
| |
| +#include <asm/segment.h> |
| + |
| +/** |
| + * mds_clear_cpu_buffers - Mitigation for MDS vulnerability |
| + * |
| + * This uses the otherwise unused and obsolete VERW instruction in |
| + * combination with microcode which triggers a CPU buffer flush when the |
| + * instruction is executed. |
| + */ |
| +static inline void mds_clear_cpu_buffers(void) |
| +{ |
| + static const u16 ds = __KERNEL_DS; |
| + |
| + /* |
| + * Has to be the memory-operand variant because only that |
| + * guarantees the CPU buffer flush functionality according to |
| + * documentation. The register-operand variant does not. |
| + * Works with any segment selector, but a valid writable |
| + * data segment is the fastest variant. |
| + * |
| + * "cc" clobber is required because VERW modifies ZF. |
| + */ |
| + asm volatile("verw %[ds]" : : [ds] "m" (ds) : "cc"); |
| +} |
| + |
| #endif /* __ASSEMBLY__ */ |
| |
| /* |
| -- |
| 2.21.0 |
| |