]>
Commit | Line | Data |
---|---|---|
b07c49f8 GKH |
1 | From ccbaead4a038a80682732de5b35841a4184678c5 Mon Sep 17 00:00:00 2001 |
2 | From: Thomas Gleixner <tglx@linutronix.de> | |
3 | Date: Mon, 18 Feb 2019 23:13:06 +0100 | |
4 | Subject: [PATCH 06/27] x86/speculation/mds: Add mds_clear_cpu_buffers() | |
5 | ||
6 | commit 6a9e529272517755904b7afa639f6db59ddb793e upstream | |
7 | ||
8 | The Microarchitectural Data Sampling (MDS) vulernabilities are mitigated by | |
9 | clearing the affected CPU buffers. The mechanism for clearing the buffers | |
10 | uses the unused and obsolete VERW instruction in combination with a | |
11 | microcode update which triggers a CPU buffer clear when VERW is executed. | |
12 | ||
13 | Provide a inline function with the assembly magic. The argument of the VERW | |
14 | instruction must be a memory operand as documented: | |
15 | ||
16 | "MD_CLEAR enumerates that the memory-operand variant of VERW (for | |
17 | example, VERW m16) has been extended to also overwrite buffers affected | |
18 | by MDS. This buffer overwriting functionality is not guaranteed for the | |
19 | register operand variant of VERW." | |
20 | ||
21 | Documentation also recommends to use a writable data segment selector: | |
22 | ||
23 | "The buffer overwriting occurs regardless of the result of the VERW | |
24 | permission check, as well as when the selector is null or causes a | |
25 | descriptor load segment violation. However, for lowest latency we | |
26 | recommend using a selector that indicates a valid writable data | |
27 | segment." | |
28 | ||
29 | Add x86 specific documentation about MDS and the internal workings of the | |
30 | mitigation. | |
31 | ||
32 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
33 | Reviewed-by: Borislav Petkov <bp@suse.de> | |
34 | Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
35 | Reviewed-by: Frederic Weisbecker <frederic@kernel.org> | |
36 | Reviewed-by: Jon Masters <jcm@redhat.com> | |
37 | Tested-by: Jon Masters <jcm@redhat.com> | |
38 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
39 | --- | |
40 | Documentation/index.rst | 1 + | |
41 | Documentation/x86/conf.py | 10 +++ | |
42 | Documentation/x86/index.rst | 8 +++ | |
43 | Documentation/x86/mds.rst | 99 ++++++++++++++++++++++++++++ | |
44 | arch/x86/include/asm/nospec-branch.h | 25 +++++++ | |
45 | 5 files changed, 143 insertions(+) | |
46 | create mode 100644 Documentation/x86/conf.py | |
47 | create mode 100644 Documentation/x86/index.rst | |
48 | create mode 100644 Documentation/x86/mds.rst | |
49 | ||
50 | diff --git a/Documentation/index.rst b/Documentation/index.rst | |
51 | index c858c2e66e36..63864826dcd6 100644 | |
52 | --- a/Documentation/index.rst | |
53 | +++ b/Documentation/index.rst | |
54 | @@ -101,6 +101,7 @@ implementation. | |
55 | :maxdepth: 2 | |
56 | ||
57 | sh/index | |
58 | + x86/index | |
59 | ||
60 | Filesystem Documentation | |
61 | ------------------------ | |
62 | diff --git a/Documentation/x86/conf.py b/Documentation/x86/conf.py | |
63 | new file mode 100644 | |
64 | index 000000000000..33c5c3142e20 | |
65 | --- /dev/null | |
66 | +++ b/Documentation/x86/conf.py | |
67 | @@ -0,0 +1,10 @@ | |
68 | +# -*- coding: utf-8; mode: python -*- | |
69 | + | |
70 | +project = "X86 architecture specific documentation" | |
71 | + | |
72 | +tags.add("subproject") | |
73 | + | |
74 | +latex_documents = [ | |
75 | + ('index', 'x86.tex', project, | |
76 | + 'The kernel development community', 'manual'), | |
77 | +] | |
78 | diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst | |
79 | new file mode 100644 | |
80 | index 000000000000..ef389dcf1b1d | |
81 | --- /dev/null | |
82 | +++ b/Documentation/x86/index.rst | |
83 | @@ -0,0 +1,8 @@ | |
84 | +========================== | |
85 | +x86 architecture specifics | |
86 | +========================== | |
87 | + | |
88 | +.. toctree:: | |
89 | + :maxdepth: 1 | |
90 | + | |
91 | + mds | |
92 | diff --git a/Documentation/x86/mds.rst b/Documentation/x86/mds.rst | |
93 | new file mode 100644 | |
94 | index 000000000000..1096738d50f2 | |
95 | --- /dev/null | |
96 | +++ b/Documentation/x86/mds.rst | |
97 | @@ -0,0 +1,99 @@ | |
98 | +Microarchitectural Data Sampling (MDS) mitigation | |
99 | +================================================= | |
100 | + | |
101 | +.. _mds: | |
102 | + | |
103 | +Overview | |
104 | +-------- | |
105 | + | |
106 | +Microarchitectural Data Sampling (MDS) is a family of side channel attacks | |
107 | +on internal buffers in Intel CPUs. The variants are: | |
108 | + | |
109 | + - Microarchitectural Store Buffer Data Sampling (MSBDS) (CVE-2018-12126) | |
110 | + - Microarchitectural Fill Buffer Data Sampling (MFBDS) (CVE-2018-12130) | |
111 | + - Microarchitectural Load Port Data Sampling (MLPDS) (CVE-2018-12127) | |
112 | + | |
113 | +MSBDS leaks Store Buffer Entries which can be speculatively forwarded to a | |
114 | +dependent load (store-to-load forwarding) as an optimization. The forward | |
115 | +can also happen to a faulting or assisting load operation for a different | |
116 | +memory address, which can be exploited under certain conditions. Store | |
117 | +buffers are partitioned between Hyper-Threads so cross thread forwarding is | |
118 | +not possible. But if a thread enters or exits a sleep state the store | |
119 | +buffer is repartitioned which can expose data from one thread to the other. | |
120 | + | |
121 | +MFBDS leaks Fill Buffer Entries. Fill buffers are used internally to manage | |
122 | +L1 miss situations and to hold data which is returned or sent in response | |
123 | +to a memory or I/O operation. Fill buffers can forward data to a load | |
124 | +operation and also write data to the cache. When the fill buffer is | |
125 | +deallocated it can retain the stale data of the preceding operations which | |
126 | +can then be forwarded to a faulting or assisting load operation, which can | |
127 | +be exploited under certain conditions. Fill buffers are shared between | |
128 | +Hyper-Threads so cross thread leakage is possible. | |
129 | + | |
130 | +MLPDS leaks Load Port Data. Load ports are used to perform load operations | |
131 | +from memory or I/O. The received data is then forwarded to the register | |
132 | +file or a subsequent operation. In some implementations the Load Port can | |
133 | +contain stale data from a previous operation which can be forwarded to | |
134 | +faulting or assisting loads under certain conditions, which again can be | |
135 | +exploited eventually. Load ports are shared between Hyper-Threads so cross | |
136 | +thread leakage is possible. | |
137 | + | |
138 | + | |
139 | +Exposure assumptions | |
140 | +-------------------- | |
141 | + | |
142 | +It is assumed that attack code resides in user space or in a guest with one | |
143 | +exception. The rationale behind this assumption is that the code construct | |
144 | +needed for exploiting MDS requires: | |
145 | + | |
146 | + - to control the load to trigger a fault or assist | |
147 | + | |
148 | + - to have a disclosure gadget which exposes the speculatively accessed | |
149 | + data for consumption through a side channel. | |
150 | + | |
151 | + - to control the pointer through which the disclosure gadget exposes the | |
152 | + data | |
153 | + | |
154 | +The existence of such a construct in the kernel cannot be excluded with | |
155 | +100% certainty, but the complexity involved makes it extremly unlikely. | |
156 | + | |
157 | +There is one exception, which is untrusted BPF. The functionality of | |
158 | +untrusted BPF is limited, but it needs to be thoroughly investigated | |
159 | +whether it can be used to create such a construct. | |
160 | + | |
161 | + | |
162 | +Mitigation strategy | |
163 | +------------------- | |
164 | + | |
165 | +All variants have the same mitigation strategy at least for the single CPU | |
166 | +thread case (SMT off): Force the CPU to clear the affected buffers. | |
167 | + | |
168 | +This is achieved by using the otherwise unused and obsolete VERW | |
169 | +instruction in combination with a microcode update. The microcode clears | |
170 | +the affected CPU buffers when the VERW instruction is executed. | |
171 | + | |
172 | +For virtualization there are two ways to achieve CPU buffer | |
173 | +clearing. Either the modified VERW instruction or via the L1D Flush | |
174 | +command. The latter is issued when L1TF mitigation is enabled so the extra | |
175 | +VERW can be avoided. If the CPU is not affected by L1TF then VERW needs to | |
176 | +be issued. | |
177 | + | |
178 | +If the VERW instruction with the supplied segment selector argument is | |
179 | +executed on a CPU without the microcode update there is no side effect | |
180 | +other than a small number of pointlessly wasted CPU cycles. | |
181 | + | |
182 | +This does not protect against cross Hyper-Thread attacks except for MSBDS | |
183 | +which is only exploitable cross Hyper-thread when one of the Hyper-Threads | |
184 | +enters a C-state. | |
185 | + | |
186 | +The kernel provides a function to invoke the buffer clearing: | |
187 | + | |
188 | + mds_clear_cpu_buffers() | |
189 | + | |
190 | +The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state | |
191 | +(idle) transitions. | |
192 | + | |
193 | +According to current knowledge additional mitigations inside the kernel | |
194 | +itself are not required because the necessary gadgets to expose the leaked | |
195 | +data cannot be controlled in a way which allows exploitation from malicious | |
196 | +user space or VM guests. | |
197 | diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h | |
198 | index dad12b767ba0..67cb9b2082b1 100644 | |
199 | --- a/arch/x86/include/asm/nospec-branch.h | |
200 | +++ b/arch/x86/include/asm/nospec-branch.h | |
201 | @@ -318,6 +318,31 @@ DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp); | |
202 | DECLARE_STATIC_KEY_FALSE(switch_mm_cond_ibpb); | |
203 | DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb); | |
204 | ||
205 | +#include <asm/segment.h> | |
206 | + | |
207 | +/** | |
208 | + * mds_clear_cpu_buffers - Mitigation for MDS vulnerability | |
209 | + * | |
210 | + * This uses the otherwise unused and obsolete VERW instruction in | |
211 | + * combination with microcode which triggers a CPU buffer flush when the | |
212 | + * instruction is executed. | |
213 | + */ | |
214 | +static inline void mds_clear_cpu_buffers(void) | |
215 | +{ | |
216 | + static const u16 ds = __KERNEL_DS; | |
217 | + | |
218 | + /* | |
219 | + * Has to be the memory-operand variant because only that | |
220 | + * guarantees the CPU buffer flush functionality according to | |
221 | + * documentation. The register-operand variant does not. | |
222 | + * Works with any segment selector, but a valid writable | |
223 | + * data segment is the fastest variant. | |
224 | + * | |
225 | + * "cc" clobber is required because VERW modifies ZF. | |
226 | + */ | |
227 | + asm volatile("verw %[ds]" : : [ds] "m" (ds) : "cc"); | |
228 | +} | |
229 | + | |
230 | #endif /* __ASSEMBLY__ */ | |
231 | ||
232 | /* | |
233 | -- | |
234 | 2.21.0 | |
235 |