]> git.proxmox.com Git - pve-kernel.git/blame - patches/kernel/0194-x86-mm-pti-Allocate-a-separate-user-PGD.patch
KPTI: add follow-up fixes
[pve-kernel.git] / patches / kernel / 0194-x86-mm-pti-Allocate-a-separate-user-PGD.patch
CommitLineData
321d628a
FG
1From 39f179e9baa1728a99a60c5933b1a4a3db73e617 Mon Sep 17 00:00:00 2001
2From: Dave Hansen <dave.hansen@linux.intel.com>
3Date: Mon, 4 Dec 2017 15:07:39 +0100
e4cdf2a5 4Subject: [PATCH 194/241] x86/mm/pti: Allocate a separate user PGD
321d628a
FG
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9CVE-2017-5754
10
11Kernel page table isolation requires to have two PGDs. One for the kernel,
12which contains the full kernel mapping plus the user space mapping and one
13for user space which contains the user space mappings and the minimal set
14of kernel mappings which are required by the architecture to be able to
15transition from and to user space.
16
17Add the necessary preliminaries.
18
19[ tglx: Split out from the big kaiser dump. EFI fixup from Kirill ]
20
21Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
22Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
23Reviewed-by: Borislav Petkov <bp@suse.de>
24Cc: Andy Lutomirski <luto@kernel.org>
25Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
26Cc: Borislav Petkov <bp@alien8.de>
27Cc: Brian Gerst <brgerst@gmail.com>
28Cc: David Laight <David.Laight@aculab.com>
29Cc: Denys Vlasenko <dvlasenk@redhat.com>
30Cc: Eduardo Valentin <eduval@amazon.com>
31Cc: Greg KH <gregkh@linuxfoundation.org>
32Cc: H. Peter Anvin <hpa@zytor.com>
33Cc: Josh Poimboeuf <jpoimboe@redhat.com>
34Cc: Juergen Gross <jgross@suse.com>
35Cc: Linus Torvalds <torvalds@linux-foundation.org>
36Cc: Peter Zijlstra <peterz@infradead.org>
37Cc: Will Deacon <will.deacon@arm.com>
38Cc: aliguori@amazon.com
39Cc: daniel.gruss@iaik.tugraz.at
40Cc: hughd@google.com
41Cc: keescook@google.com
42Signed-off-by: Ingo Molnar <mingo@kernel.org>
43(backported from commit d9e9a6418065bb376e5de8d93ce346939b9a37a6)
44Signed-off-by: Andy Whitcroft <apw@canonical.com>
45Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
46(cherry picked from commit 0bd4b34e330d8bedf90c0497dfcef2e2286c4367)
47Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
48---
49 arch/x86/include/asm/pgalloc.h | 11 +++++++++++
50 arch/x86/mm/pgtable.c | 5 +++--
51 arch/x86/platform/efi/efi_64.c | 5 ++++-
52 arch/x86/kernel/head_64.S | 30 +++++++++++++++++++++++++++---
53 4 files changed, 45 insertions(+), 6 deletions(-)
54
55diff --git a/arch/x86/include/asm/pgalloc.h b/arch/x86/include/asm/pgalloc.h
56index b2d0cd8288aa..d65b0dee7448 100644
57--- a/arch/x86/include/asm/pgalloc.h
58+++ b/arch/x86/include/asm/pgalloc.h
59@@ -29,6 +29,17 @@ static inline void paravirt_release_p4d(unsigned long pfn) {}
60 */
61 extern gfp_t __userpte_alloc_gfp;
62
63+#ifdef CONFIG_PAGE_TABLE_ISOLATION
64+/*
65+ * Instead of one PGD, we acquire two PGDs. Being order-1, it is
66+ * both 8k in size and 8k-aligned. That lets us just flip bit 12
67+ * in a pointer to swap between the two 4k halves.
68+ */
69+#define PGD_ALLOCATION_ORDER 1
70+#else
71+#define PGD_ALLOCATION_ORDER 0
72+#endif
73+
74 /*
75 * Allocate and free page tables.
76 */
77diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
78index 942391b5b639..90d1d8f49cf6 100644
79--- a/arch/x86/mm/pgtable.c
80+++ b/arch/x86/mm/pgtable.c
81@@ -354,14 +354,15 @@ static inline void _pgd_free(pgd_t *pgd)
82 kmem_cache_free(pgd_cache, pgd);
83 }
84 #else
85+
86 static inline pgd_t *_pgd_alloc(void)
87 {
88- return (pgd_t *)__get_free_page(PGALLOC_GFP);
89+ return (pgd_t *)__get_free_pages(PGALLOC_GFP, PGD_ALLOCATION_ORDER);
90 }
91
92 static inline void _pgd_free(pgd_t *pgd)
93 {
94- free_page((unsigned long)pgd);
95+ free_pages((unsigned long)pgd, PGD_ALLOCATION_ORDER);
96 }
97 #endif /* CONFIG_X86_PAE */
98
99diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
100index 9bf72f5bfedb..b104224d3d6c 100644
101--- a/arch/x86/platform/efi/efi_64.c
102+++ b/arch/x86/platform/efi/efi_64.c
103@@ -194,6 +194,9 @@ static pgd_t *efi_pgd;
104 * because we want to avoid inserting EFI region mappings (EFI_VA_END
105 * to EFI_VA_START) into the standard kernel page tables. Everything
106 * else can be shared, see efi_sync_low_kernel_mappings().
107+ *
108+ * We don't want the pgd on the pgd_list and cannot use pgd_alloc() for the
109+ * allocation.
110 */
111 int __init efi_alloc_page_tables(void)
112 {
113@@ -206,7 +209,7 @@ int __init efi_alloc_page_tables(void)
114 return 0;
115
116 gfp_mask = GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO;
117- efi_pgd = (pgd_t *)__get_free_page(gfp_mask);
118+ efi_pgd = (pgd_t *)__get_free_pages(gfp_mask, PGD_ALLOCATION_ORDER);
119 if (!efi_pgd)
120 return -ENOMEM;
121
122diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
123index e785734980ad..eeaaaab54b2a 100644
124--- a/arch/x86/kernel/head_64.S
125+++ b/arch/x86/kernel/head_64.S
126@@ -324,6 +324,27 @@ GLOBAL(early_recursion_flag)
127 .balign PAGE_SIZE; \
128 GLOBAL(name)
129
130+#ifdef CONFIG_PAGE_TABLE_ISOLATION
131+/*
132+ * Each PGD needs to be 8k long and 8k aligned. We do not
133+ * ever go out to userspace with these, so we do not
134+ * strictly *need* the second page, but this allows us to
135+ * have a single set_pgd() implementation that does not
136+ * need to worry about whether it has 4k or 8k to work
137+ * with.
138+ *
139+ * This ensures PGDs are 8k long:
140+ */
141+#define PTI_USER_PGD_FILL 512
142+/* This ensures they are 8k-aligned: */
143+#define NEXT_PGD_PAGE(name) \
144+ .balign 2 * PAGE_SIZE; \
145+GLOBAL(name)
146+#else
147+#define NEXT_PGD_PAGE(name) NEXT_PAGE(name)
148+#define PTI_USER_PGD_FILL 0
149+#endif
150+
151 /* Automate the creation of 1 to 1 mapping pmd entries */
152 #define PMDS(START, PERM, COUNT) \
153 i = 0 ; \
154@@ -333,13 +354,14 @@ GLOBAL(name)
155 .endr
156
157 __INITDATA
158-NEXT_PAGE(early_top_pgt)
159+NEXT_PGD_PAGE(early_top_pgt)
160 .fill 511,8,0
161 #ifdef CONFIG_X86_5LEVEL
162 .quad level4_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
163 #else
164 .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
165 #endif
166+ .fill PTI_USER_PGD_FILL,8,0
167
168 NEXT_PAGE(early_dynamic_pgts)
169 .fill 512*EARLY_DYNAMIC_PAGE_TABLES,8,0
170@@ -347,13 +369,14 @@ NEXT_PAGE(early_dynamic_pgts)
171 .data
172
173 #if defined(CONFIG_XEN_PV) || defined(CONFIG_XEN_PVH)
174-NEXT_PAGE(init_top_pgt)
175+NEXT_PGD_PAGE(init_top_pgt)
176 .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
177 .org init_top_pgt + PGD_PAGE_OFFSET*8, 0
178 .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
179 .org init_top_pgt + PGD_START_KERNEL*8, 0
180 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
181 .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
182+ .fill PTI_USER_PGD_FILL,8,0
183
184 NEXT_PAGE(level3_ident_pgt)
185 .quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
186@@ -364,8 +387,9 @@ NEXT_PAGE(level2_ident_pgt)
187 */
188 PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD)
189 #else
190-NEXT_PAGE(init_top_pgt)
191+NEXT_PGD_PAGE(init_top_pgt)
192 .fill 512,8,0
193+ .fill PTI_USER_PGD_FILL,8,0
194 #endif
195
196 #ifdef CONFIG_X86_5LEVEL
197--
1982.14.2
199