]>
Commit | Line | Data |
---|---|---|
59d5af67 | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
321d628a FG |
2 | From: Thomas Gleixner <tglx@linutronix.de> |
3 | Date: Mon, 4 Dec 2017 15:07:36 +0100 | |
59d5af67 | 4 | Subject: [PATCH] x86/mm/pti: Add infrastructure for page table isolation |
321d628a FG |
5 | MIME-Version: 1.0 |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | CVE-2017-5754 | |
10 | ||
11 | Add the initial files for kernel page table isolation, with a minimal init | |
12 | function and the boot time detection for this misfeature. | |
13 | ||
14 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
15 | Reviewed-by: Borislav Petkov <bp@suse.de> | |
16 | Cc: Andy Lutomirski <luto@kernel.org> | |
17 | Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> | |
18 | Cc: Borislav Petkov <bp@alien8.de> | |
19 | Cc: Brian Gerst <brgerst@gmail.com> | |
20 | Cc: Dave Hansen <dave.hansen@linux.intel.com> | |
21 | Cc: David Laight <David.Laight@aculab.com> | |
22 | Cc: Denys Vlasenko <dvlasenk@redhat.com> | |
23 | Cc: Eduardo Valentin <eduval@amazon.com> | |
24 | Cc: Greg KH <gregkh@linuxfoundation.org> | |
25 | Cc: H. Peter Anvin <hpa@zytor.com> | |
26 | Cc: Josh Poimboeuf <jpoimboe@redhat.com> | |
27 | Cc: Juergen Gross <jgross@suse.com> | |
28 | Cc: Linus Torvalds <torvalds@linux-foundation.org> | |
29 | Cc: Peter Zijlstra <peterz@infradead.org> | |
30 | Cc: Will Deacon <will.deacon@arm.com> | |
31 | Cc: aliguori@amazon.com | |
32 | Cc: daniel.gruss@iaik.tugraz.at | |
33 | Cc: hughd@google.com | |
34 | Cc: keescook@google.com | |
35 | Signed-off-by: Ingo Molnar <mingo@kernel.org> | |
36 | (backported from commit aa8c6248f8c75acfd610fe15d8cae23cf70d9d09) | |
37 | Signed-off-by: Andy Whitcroft <apw@canonical.com> | |
38 | Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> | |
39 | (cherry picked from commit 50da124a01ed7a59f9b2c9551f622c5a27d1caec) | |
40 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
41 | --- | |
42 | Documentation/admin-guide/kernel-parameters.txt | 2 + | |
43 | arch/x86/mm/Makefile | 7 ++- | |
44 | arch/x86/entry/calling.h | 7 +++ | |
45 | arch/x86/include/asm/pti.h | 14 +++++ | |
46 | include/linux/pti.h | 11 ++++ | |
47 | arch/x86/boot/compressed/pagetable.c | 3 + | |
48 | arch/x86/mm/init.c | 2 + | |
49 | arch/x86/mm/pti.c | 84 +++++++++++++++++++++++++ | |
50 | init/main.c | 3 + | |
51 | 9 files changed, 130 insertions(+), 3 deletions(-) | |
52 | create mode 100644 arch/x86/include/asm/pti.h | |
53 | create mode 100644 include/linux/pti.h | |
54 | create mode 100644 arch/x86/mm/pti.c | |
55 | ||
56 | diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt | |
57 | index 3510e255ef4c..e2a4608da5d2 100644 | |
58 | --- a/Documentation/admin-guide/kernel-parameters.txt | |
59 | +++ b/Documentation/admin-guide/kernel-parameters.txt | |
60 | @@ -2677,6 +2677,8 @@ | |
61 | steal time is computed, but won't influence scheduler | |
62 | behaviour | |
63 | ||
64 | + nopti [X86-64] Disable kernel page table isolation | |
65 | + | |
66 | nolapic [X86-32,APIC] Do not enable or use the local APIC. | |
67 | ||
68 | nolapic_timer [X86-32,APIC] Do not use the local APIC timer. | |
69 | diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile | |
70 | index 76f5399a8356..7aa68fc18abe 100644 | |
71 | --- a/arch/x86/mm/Makefile | |
72 | +++ b/arch/x86/mm/Makefile | |
73 | @@ -35,7 +35,8 @@ obj-$(CONFIG_AMD_NUMA) += amdtopology.o | |
74 | obj-$(CONFIG_ACPI_NUMA) += srat.o | |
75 | obj-$(CONFIG_NUMA_EMU) += numa_emulation.o | |
76 | ||
77 | -obj-$(CONFIG_X86_INTEL_MPX) += mpx.o | |
78 | -obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o | |
79 | -obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o | |
80 | +obj-$(CONFIG_X86_INTEL_MPX) += mpx.o | |
81 | +obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o | |
82 | +obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o | |
83 | +obj-$(CONFIG_PAGE_TABLE_ISOLATION) += pti.o | |
84 | ||
85 | diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h | |
86 | index dde6262be0a3..bb56f5346ae8 100644 | |
87 | --- a/arch/x86/entry/calling.h | |
88 | +++ b/arch/x86/entry/calling.h | |
89 | @@ -204,18 +204,23 @@ For 32-bit we have the following conventions - kernel is built with | |
90 | .endm | |
91 | ||
92 | .macro SWITCH_TO_KERNEL_CR3 scratch_reg:req | |
93 | + ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI | |
94 | mov %cr3, \scratch_reg | |
95 | ADJUST_KERNEL_CR3 \scratch_reg | |
96 | mov \scratch_reg, %cr3 | |
97 | +.Lend_\@: | |
98 | .endm | |
99 | ||
100 | .macro SWITCH_TO_USER_CR3 scratch_reg:req | |
101 | + ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI | |
102 | mov %cr3, \scratch_reg | |
103 | ADJUST_USER_CR3 \scratch_reg | |
104 | mov \scratch_reg, %cr3 | |
105 | +.Lend_\@: | |
106 | .endm | |
107 | ||
108 | .macro SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg:req save_reg:req | |
109 | + ALTERNATIVE "jmp .Ldone_\@", "", X86_FEATURE_PTI | |
110 | movq %cr3, \scratch_reg | |
111 | movq \scratch_reg, \save_reg | |
112 | /* | |
113 | @@ -232,11 +237,13 @@ For 32-bit we have the following conventions - kernel is built with | |
114 | .endm | |
115 | ||
116 | .macro RESTORE_CR3 save_reg:req | |
117 | + ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI | |
118 | /* | |
119 | * The CR3 write could be avoided when not changing its value, | |
120 | * but would require a CR3 read *and* a scratch register. | |
121 | */ | |
122 | movq \save_reg, %cr3 | |
123 | +.Lend_\@: | |
124 | .endm | |
125 | ||
126 | #else /* CONFIG_PAGE_TABLE_ISOLATION=n: */ | |
127 | diff --git a/arch/x86/include/asm/pti.h b/arch/x86/include/asm/pti.h | |
128 | new file mode 100644 | |
129 | index 000000000000..0b5ef05b2d2d | |
130 | --- /dev/null | |
131 | +++ b/arch/x86/include/asm/pti.h | |
132 | @@ -0,0 +1,14 @@ | |
133 | +// SPDX-License-Identifier: GPL-2.0 | |
134 | +#ifndef _ASM_X86_PTI_H | |
135 | +#define _ASM_X86_PTI_H | |
136 | +#ifndef __ASSEMBLY__ | |
137 | + | |
138 | +#ifdef CONFIG_PAGE_TABLE_ISOLATION | |
139 | +extern void pti_init(void); | |
140 | +extern void pti_check_boottime_disable(void); | |
141 | +#else | |
142 | +static inline void pti_check_boottime_disable(void) { } | |
143 | +#endif | |
144 | + | |
145 | +#endif /* __ASSEMBLY__ */ | |
146 | +#endif /* _ASM_X86_PTI_H */ | |
147 | diff --git a/include/linux/pti.h b/include/linux/pti.h | |
148 | new file mode 100644 | |
149 | index 000000000000..0174883a935a | |
150 | --- /dev/null | |
151 | +++ b/include/linux/pti.h | |
152 | @@ -0,0 +1,11 @@ | |
153 | +// SPDX-License-Identifier: GPL-2.0 | |
154 | +#ifndef _INCLUDE_PTI_H | |
155 | +#define _INCLUDE_PTI_H | |
156 | + | |
157 | +#ifdef CONFIG_PAGE_TABLE_ISOLATION | |
158 | +#include <asm/pti.h> | |
159 | +#else | |
160 | +static inline void pti_init(void) { } | |
161 | +#endif | |
162 | + | |
163 | +#endif | |
164 | diff --git a/arch/x86/boot/compressed/pagetable.c b/arch/x86/boot/compressed/pagetable.c | |
165 | index 28029be47fbb..21d8839cdaa7 100644 | |
166 | --- a/arch/x86/boot/compressed/pagetable.c | |
167 | +++ b/arch/x86/boot/compressed/pagetable.c | |
168 | @@ -15,6 +15,9 @@ | |
169 | #define __pa(x) ((unsigned long)(x)) | |
170 | #define __va(x) ((void *)((unsigned long)(x))) | |
171 | ||
172 | +/* No PAGE_TABLE_ISOLATION support needed either: */ | |
173 | +#undef CONFIG_PAGE_TABLE_ISOLATION | |
174 | + | |
175 | #include "misc.h" | |
176 | ||
177 | /* These actually do the work of building the kernel identity maps. */ | |
178 | diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c | |
179 | index 020223420308..af75069fb116 100644 | |
180 | --- a/arch/x86/mm/init.c | |
181 | +++ b/arch/x86/mm/init.c | |
182 | @@ -20,6 +20,7 @@ | |
183 | #include <asm/kaslr.h> | |
184 | #include <asm/hypervisor.h> | |
185 | #include <asm/cpufeature.h> | |
186 | +#include <asm/pti.h> | |
187 | ||
188 | /* | |
189 | * We need to define the tracepoints somewhere, and tlb.c | |
190 | @@ -630,6 +631,7 @@ void __init init_mem_mapping(void) | |
191 | { | |
192 | unsigned long end; | |
193 | ||
194 | + pti_check_boottime_disable(); | |
195 | probe_page_size_mask(); | |
196 | setup_pcid(); | |
197 | ||
198 | diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c | |
199 | new file mode 100644 | |
200 | index 000000000000..375f23a758bc | |
201 | --- /dev/null | |
202 | +++ b/arch/x86/mm/pti.c | |
203 | @@ -0,0 +1,84 @@ | |
204 | +/* | |
205 | + * Copyright(c) 2017 Intel Corporation. All rights reserved. | |
206 | + * | |
207 | + * This program is free software; you can redistribute it and/or modify | |
208 | + * it under the terms of version 2 of the GNU General Public License as | |
209 | + * published by the Free Software Foundation. | |
210 | + * | |
211 | + * This program is distributed in the hope that it will be useful, but | |
212 | + * WITHOUT ANY WARRANTY; without even the implied warranty of | |
213 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
214 | + * General Public License for more details. | |
215 | + * | |
216 | + * This code is based in part on work published here: | |
217 | + * | |
218 | + * https://github.com/IAIK/KAISER | |
219 | + * | |
220 | + * The original work was written by and and signed off by for the Linux | |
221 | + * kernel by: | |
222 | + * | |
223 | + * Signed-off-by: Richard Fellner <richard.fellner@student.tugraz.at> | |
224 | + * Signed-off-by: Moritz Lipp <moritz.lipp@iaik.tugraz.at> | |
225 | + * Signed-off-by: Daniel Gruss <daniel.gruss@iaik.tugraz.at> | |
226 | + * Signed-off-by: Michael Schwarz <michael.schwarz@iaik.tugraz.at> | |
227 | + * | |
228 | + * Major changes to the original code by: Dave Hansen <dave.hansen@intel.com> | |
229 | + * Mostly rewritten by Thomas Gleixner <tglx@linutronix.de> and | |
230 | + * Andy Lutomirsky <luto@amacapital.net> | |
231 | + */ | |
232 | +#include <linux/kernel.h> | |
233 | +#include <linux/errno.h> | |
234 | +#include <linux/string.h> | |
235 | +#include <linux/types.h> | |
236 | +#include <linux/bug.h> | |
237 | +#include <linux/init.h> | |
238 | +#include <linux/spinlock.h> | |
239 | +#include <linux/mm.h> | |
240 | +#include <linux/uaccess.h> | |
241 | + | |
242 | +#include <asm/cpufeature.h> | |
243 | +#include <asm/hypervisor.h> | |
244 | +#include <asm/cmdline.h> | |
245 | +#include <asm/pti.h> | |
246 | +#include <asm/pgtable.h> | |
247 | +#include <asm/pgalloc.h> | |
248 | +#include <asm/tlbflush.h> | |
249 | +#include <asm/desc.h> | |
250 | + | |
251 | +#undef pr_fmt | |
252 | +#define pr_fmt(fmt) "Kernel/User page tables isolation: " fmt | |
253 | + | |
254 | +static void __init pti_print_if_insecure(const char *reason) | |
255 | +{ | |
256 | + if (boot_cpu_has_bug(X86_BUG_CPU_INSECURE)) | |
257 | + pr_info("%s\n", reason); | |
258 | +} | |
259 | + | |
260 | +void __init pti_check_boottime_disable(void) | |
261 | +{ | |
262 | + if (hypervisor_is_type(X86_HYPER_XEN_PV)) { | |
263 | + pti_print_if_insecure("disabled on XEN PV."); | |
264 | + return; | |
265 | + } | |
266 | + | |
267 | + if (cmdline_find_option_bool(boot_command_line, "nopti")) { | |
268 | + pti_print_if_insecure("disabled on command line."); | |
269 | + return; | |
270 | + } | |
271 | + | |
272 | + if (!boot_cpu_has_bug(X86_BUG_CPU_INSECURE)) | |
273 | + return; | |
274 | + | |
275 | + setup_force_cpu_cap(X86_FEATURE_PTI); | |
276 | +} | |
277 | + | |
278 | +/* | |
279 | + * Initialize kernel page table isolation | |
280 | + */ | |
281 | +void __init pti_init(void) | |
282 | +{ | |
283 | + if (!static_cpu_has(X86_FEATURE_PTI)) | |
284 | + return; | |
285 | + | |
286 | + pr_info("enabled\n"); | |
287 | +} | |
288 | diff --git a/init/main.c b/init/main.c | |
289 | index de1c495da782..bb0896c24c08 100644 | |
290 | --- a/init/main.c | |
291 | +++ b/init/main.c | |
292 | @@ -75,6 +75,7 @@ | |
293 | #include <linux/slab.h> | |
294 | #include <linux/perf_event.h> | |
295 | #include <linux/ptrace.h> | |
296 | +#include <linux/pti.h> | |
297 | #include <linux/blkdev.h> | |
298 | #include <linux/elevator.h> | |
299 | #include <linux/sched_clock.h> | |
300 | @@ -506,6 +507,8 @@ static void __init mm_init(void) | |
301 | ioremap_huge_init(); | |
302 | /* Should be run before the first non-init thread is created */ | |
303 | init_espfix_bsp(); | |
304 | + /* Should be run after espfix64 is set up. */ | |
305 | + pti_init(); | |
306 | } | |
307 | ||
308 | asmlinkage __visible void __init start_kernel(void) | |
309 | -- | |
310 | 2.14.2 | |
311 |