aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Ryabinin <aryabinin@virtuozzo.com>2017-09-29 10:08:18 -0400
committerIngo Molnar <mingo@kernel.org>2017-10-20 07:07:09 -0400
commit12a8cc7fcf54a8575f094be1e99032ec38aa045c (patch)
tree72e1c6c0390c1e78617129e4fe9fafb215fd52d4
parent83e3c48729d9ebb7af5a31a504f3fd6aff0348c4 (diff)
x86/kasan: Use the same shadow offset for 4- and 5-level paging
We are going to support boot-time switching between 4- and 5-level paging. For KASAN it means we cannot have different KASAN_SHADOW_OFFSET for different paging modes: the constant is passed to gcc to generate code and cannot be changed at runtime. This patch changes KASAN code to use 0xdffffc0000000000 as shadow offset for both 4- and 5-level paging. For 5-level paging it means that shadow memory region is not aligned to PGD boundary anymore and we have to handle unaligned parts of the region properly. In addition, we have to exclude paravirt code from KASAN instrumentation as we now use set_pgd() before KASAN is fully ready. [kirill.shutemov@linux.intel.com: clenaup, changelog message] Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@suse.de> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20170929140821.37654-4-kirill.shutemov@linux.intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--Documentation/x86/x86_64/mm.txt2
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/kernel/Makefile3
-rw-r--r--arch/x86/mm/kasan_init_64.c101
4 files changed, 83 insertions, 24 deletions
diff --git a/Documentation/x86/x86_64/mm.txt b/Documentation/x86/x86_64/mm.txt
index b0798e281aa6..3448e675b462 100644
--- a/Documentation/x86/x86_64/mm.txt
+++ b/Documentation/x86/x86_64/mm.txt
@@ -34,7 +34,7 @@ ff92000000000000 - ffd1ffffffffffff (=54 bits) vmalloc/ioremap space
34ffd2000000000000 - ffd3ffffffffffff (=49 bits) hole 34ffd2000000000000 - ffd3ffffffffffff (=49 bits) hole
35ffd4000000000000 - ffd5ffffffffffff (=49 bits) virtual memory map (512TB) 35ffd4000000000000 - ffd5ffffffffffff (=49 bits) virtual memory map (512TB)
36... unused hole ... 36... unused hole ...
37ffd8000000000000 - fff7ffffffffffff (=53 bits) kasan shadow memory (8PB) 37ffdf000000000000 - fffffc0000000000 (=53 bits) kasan shadow memory (8PB)
38... unused hole ... 38... unused hole ...
39ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks 39ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks
40... unused hole ... 40... unused hole ...
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 971feac13506..32779beb56e2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -302,7 +302,6 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
302config KASAN_SHADOW_OFFSET 302config KASAN_SHADOW_OFFSET
303 hex 303 hex
304 depends on KASAN 304 depends on KASAN
305 default 0xdff8000000000000 if X86_5LEVEL
306 default 0xdffffc0000000000 305 default 0xdffffc0000000000
307 306
308config HAVE_INTEL_TXT 307config HAVE_INTEL_TXT
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index fd0a7895b63f..a97a6b611531 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -24,7 +24,8 @@ endif
24KASAN_SANITIZE_head$(BITS).o := n 24KASAN_SANITIZE_head$(BITS).o := n
25KASAN_SANITIZE_dumpstack.o := n 25KASAN_SANITIZE_dumpstack.o := n
26KASAN_SANITIZE_dumpstack_$(BITS).o := n 26KASAN_SANITIZE_dumpstack_$(BITS).o := n
27KASAN_SANITIZE_stacktrace.o := n 27KASAN_SANITIZE_stacktrace.o := n
28KASAN_SANITIZE_paravirt.o := n
28 29
29OBJECT_FILES_NON_STANDARD_head_$(BITS).o := y 30OBJECT_FILES_NON_STANDARD_head_$(BITS).o := y
30OBJECT_FILES_NON_STANDARD_relocate_kernel_$(BITS).o := y 31OBJECT_FILES_NON_STANDARD_relocate_kernel_$(BITS).o := y
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index bc84b73684b7..fe5760db7b19 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -15,6 +15,8 @@
15 15
16extern struct range pfn_mapped[E820_MAX_ENTRIES]; 16extern struct range pfn_mapped[E820_MAX_ENTRIES];
17 17
18static p4d_t tmp_p4d_table[PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE);
19
18static int __init map_range(struct range *range) 20static int __init map_range(struct range *range)
19{ 21{
20 unsigned long start; 22 unsigned long start;
@@ -30,8 +32,10 @@ static void __init clear_pgds(unsigned long start,
30 unsigned long end) 32 unsigned long end)
31{ 33{
32 pgd_t *pgd; 34 pgd_t *pgd;
35 /* See comment in kasan_init() */
36 unsigned long pgd_end = end & PGDIR_MASK;
33 37
34 for (; start < end; start += PGDIR_SIZE) { 38 for (; start < pgd_end; start += PGDIR_SIZE) {
35 pgd = pgd_offset_k(start); 39 pgd = pgd_offset_k(start);
36 /* 40 /*
37 * With folded p4d, pgd_clear() is nop, use p4d_clear() 41 * With folded p4d, pgd_clear() is nop, use p4d_clear()
@@ -42,29 +46,61 @@ static void __init clear_pgds(unsigned long start,
42 else 46 else
43 pgd_clear(pgd); 47 pgd_clear(pgd);
44 } 48 }
49
50 pgd = pgd_offset_k(start);
51 for (; start < end; start += P4D_SIZE)
52 p4d_clear(p4d_offset(pgd, start));
53}
54
55static inline p4d_t *early_p4d_offset(pgd_t *pgd, unsigned long addr)
56{
57 unsigned long p4d;
58
59 if (!IS_ENABLED(CONFIG_X86_5LEVEL))
60 return (p4d_t *)pgd;
61
62 p4d = __pa_nodebug(pgd_val(*pgd)) & PTE_PFN_MASK;
63 p4d += __START_KERNEL_map - phys_base;
64 return (p4d_t *)p4d + p4d_index(addr);
65}
66
67static void __init kasan_early_p4d_populate(pgd_t *pgd,
68 unsigned long addr,
69 unsigned long end)
70{
71 pgd_t pgd_entry;
72 p4d_t *p4d, p4d_entry;
73 unsigned long next;
74
75 if (pgd_none(*pgd)) {
76 pgd_entry = __pgd(_KERNPG_TABLE | __pa_nodebug(kasan_zero_p4d));
77 set_pgd(pgd, pgd_entry);
78 }
79
80 p4d = early_p4d_offset(pgd, addr);
81 do {
82 next = p4d_addr_end(addr, end);
83
84 if (!p4d_none(*p4d))
85 continue;
86
87 p4d_entry = __p4d(_KERNPG_TABLE | __pa_nodebug(kasan_zero_pud));
88 set_p4d(p4d, p4d_entry);
89 } while (p4d++, addr = next, addr != end && p4d_none(*p4d));
45} 90}
46 91
47static void __init kasan_map_early_shadow(pgd_t *pgd) 92static void __init kasan_map_early_shadow(pgd_t *pgd)
48{ 93{
49 int i; 94 /* See comment in kasan_init() */
50 unsigned long start = KASAN_SHADOW_START; 95 unsigned long addr = KASAN_SHADOW_START & PGDIR_MASK;
51 unsigned long end = KASAN_SHADOW_END; 96 unsigned long end = KASAN_SHADOW_END;
97 unsigned long next;
52 98
53 for (i = pgd_index(start); start < end; i++) { 99 pgd += pgd_index(addr);
54 switch (CONFIG_PGTABLE_LEVELS) { 100 do {
55 case 4: 101 next = pgd_addr_end(addr, end);
56 pgd[i] = __pgd(__pa_nodebug(kasan_zero_pud) | 102 kasan_early_p4d_populate(pgd, addr, next);
57 _KERNPG_TABLE); 103 } while (pgd++, addr = next, addr != end);
58 break;
59 case 5:
60 pgd[i] = __pgd(__pa_nodebug(kasan_zero_p4d) |
61 _KERNPG_TABLE);
62 break;
63 default:
64 BUILD_BUG();
65 }
66 start += PGDIR_SIZE;
67 }
68} 104}
69 105
70#ifdef CONFIG_KASAN_INLINE 106#ifdef CONFIG_KASAN_INLINE
@@ -101,7 +137,7 @@ void __init kasan_early_init(void)
101 for (i = 0; i < PTRS_PER_PUD; i++) 137 for (i = 0; i < PTRS_PER_PUD; i++)
102 kasan_zero_pud[i] = __pud(pud_val); 138 kasan_zero_pud[i] = __pud(pud_val);
103 139
104 for (i = 0; CONFIG_PGTABLE_LEVELS >= 5 && i < PTRS_PER_P4D; i++) 140 for (i = 0; IS_ENABLED(CONFIG_X86_5LEVEL) && i < PTRS_PER_P4D; i++)
105 kasan_zero_p4d[i] = __p4d(p4d_val); 141 kasan_zero_p4d[i] = __p4d(p4d_val);
106 142
107 kasan_map_early_shadow(early_top_pgt); 143 kasan_map_early_shadow(early_top_pgt);
@@ -117,12 +153,35 @@ void __init kasan_init(void)
117#endif 153#endif
118 154
119 memcpy(early_top_pgt, init_top_pgt, sizeof(early_top_pgt)); 155 memcpy(early_top_pgt, init_top_pgt, sizeof(early_top_pgt));
156
157 /*
158 * We use the same shadow offset for 4- and 5-level paging to
159 * facilitate boot-time switching between paging modes.
160 * As result in 5-level paging mode KASAN_SHADOW_START and
161 * KASAN_SHADOW_END are not aligned to PGD boundary.
162 *
163 * KASAN_SHADOW_START doesn't share PGD with anything else.
164 * We claim whole PGD entry to make things easier.
165 *
166 * KASAN_SHADOW_END lands in the last PGD entry and it collides with
167 * bunch of things like kernel code, modules, EFI mapping, etc.
168 * We need to take extra steps to not overwrite them.
169 */
170 if (IS_ENABLED(CONFIG_X86_5LEVEL)) {
171 void *ptr;
172
173 ptr = (void *)pgd_page_vaddr(*pgd_offset_k(KASAN_SHADOW_END));
174 memcpy(tmp_p4d_table, (void *)ptr, sizeof(tmp_p4d_table));
175 set_pgd(&early_top_pgt[pgd_index(KASAN_SHADOW_END)],
176 __pgd(__pa(tmp_p4d_table) | _KERNPG_TABLE));
177 }
178
120 load_cr3(early_top_pgt); 179 load_cr3(early_top_pgt);
121 __flush_tlb_all(); 180 __flush_tlb_all();
122 181
123 clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END); 182 clear_pgds(KASAN_SHADOW_START & PGDIR_MASK, KASAN_SHADOW_END);
124 183
125 kasan_populate_zero_shadow((void *)KASAN_SHADOW_START, 184 kasan_populate_zero_shadow((void *)(KASAN_SHADOW_START & PGDIR_MASK),
126 kasan_mem_to_shadow((void *)PAGE_OFFSET)); 185 kasan_mem_to_shadow((void *)PAGE_OFFSET));
127 186
128 for (i = 0; i < E820_MAX_ENTRIES; i++) { 187 for (i = 0; i < E820_MAX_ENTRIES; i++) {