| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- From f6bb8e560b2229af5dcf3127fc92e732539b4823 Mon Sep 17 00:00:00 2001
- From: Andrey Ryabinin <[email protected]>
- Date: Fri, 29 Sep 2017 17:08:18 +0300
- Subject: [PATCH 075/242] x86/kasan: Use the same shadow offset for 4- and
- 5-level paging
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- CVE-2017-5754
- 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.
- [[email protected]: clenaup, changelog message]
- Signed-off-by: Andrey Ryabinin <[email protected]>
- Signed-off-by: Kirill A. Shutemov <[email protected]>
- Cc: Andrew Morton <[email protected]>
- Cc: Andy Lutomirski <[email protected]>
- Cc: Borislav Petkov <[email protected]>
- Cc: Cyrill Gorcunov <[email protected]>
- Cc: Linus Torvalds <[email protected]>
- Cc: Peter Zijlstra <[email protected]>
- Cc: Thomas Gleixner <[email protected]>
- Cc: [email protected]
- Link: http://lkml.kernel.org/r/[email protected]
- Signed-off-by: Ingo Molnar <[email protected]>
- (cherry picked from commit 12a8cc7fcf54a8575f094be1e99032ec38aa045c)
- Signed-off-by: Andy Whitcroft <[email protected]>
- Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
- (cherry picked from commit 2ce428150e002623aa0ed2a1ab840fde5f860f32)
- Signed-off-by: Fabian Grünbichler <[email protected]>
- ---
- Documentation/x86/x86_64/mm.txt | 2 +-
- arch/x86/kernel/Makefile | 3 +-
- arch/x86/mm/kasan_init_64.c | 101 +++++++++++++++++++++++++++++++---------
- arch/x86/Kconfig | 1 -
- 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
- ffd2000000000000 - ffd3ffffffffffff (=49 bits) hole
- ffd4000000000000 - ffd5ffffffffffff (=49 bits) virtual memory map (512TB)
- ... unused hole ...
- -ffd8000000000000 - fff7ffffffffffff (=53 bits) kasan shadow memory (8PB)
- +ffdf000000000000 - fffffc0000000000 (=53 bits) kasan shadow memory (8PB)
- ... unused hole ...
- ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks
- ... unused hole ...
- diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
- index 5bf0d5a473b4..aa059806201d 100644
- --- a/arch/x86/kernel/Makefile
- +++ b/arch/x86/kernel/Makefile
- @@ -24,7 +24,8 @@ endif
- KASAN_SANITIZE_head$(BITS).o := n
- KASAN_SANITIZE_dumpstack.o := n
- KASAN_SANITIZE_dumpstack_$(BITS).o := n
- -KASAN_SANITIZE_stacktrace.o := n
- +KASAN_SANITIZE_stacktrace.o := n
- +KASAN_SANITIZE_paravirt.o := n
-
- OBJECT_FILES_NON_STANDARD_relocate_kernel_$(BITS).o := y
- OBJECT_FILES_NON_STANDARD_ftrace_$(BITS).o := y
- diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
- index 02c9d7553409..464089f33e80 100644
- --- a/arch/x86/mm/kasan_init_64.c
- +++ b/arch/x86/mm/kasan_init_64.c
- @@ -15,6 +15,8 @@
- extern pgd_t early_top_pgt[PTRS_PER_PGD];
- extern struct range pfn_mapped[E820_MAX_ENTRIES];
-
- +static p4d_t tmp_p4d_table[PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE);
- +
- static int __init map_range(struct range *range)
- {
- unsigned long start;
- @@ -30,8 +32,10 @@ static void __init clear_pgds(unsigned long start,
- unsigned long end)
- {
- pgd_t *pgd;
- + /* See comment in kasan_init() */
- + unsigned long pgd_end = end & PGDIR_MASK;
-
- - for (; start < end; start += PGDIR_SIZE) {
- + for (; start < pgd_end; start += PGDIR_SIZE) {
- pgd = pgd_offset_k(start);
- /*
- * With folded p4d, pgd_clear() is nop, use p4d_clear()
- @@ -42,29 +46,61 @@ static void __init clear_pgds(unsigned long start,
- else
- pgd_clear(pgd);
- }
- +
- + pgd = pgd_offset_k(start);
- + for (; start < end; start += P4D_SIZE)
- + p4d_clear(p4d_offset(pgd, start));
- +}
- +
- +static inline p4d_t *early_p4d_offset(pgd_t *pgd, unsigned long addr)
- +{
- + unsigned long p4d;
- +
- + if (!IS_ENABLED(CONFIG_X86_5LEVEL))
- + return (p4d_t *)pgd;
- +
- + p4d = __pa_nodebug(pgd_val(*pgd)) & PTE_PFN_MASK;
- + p4d += __START_KERNEL_map - phys_base;
- + return (p4d_t *)p4d + p4d_index(addr);
- +}
- +
- +static void __init kasan_early_p4d_populate(pgd_t *pgd,
- + unsigned long addr,
- + unsigned long end)
- +{
- + pgd_t pgd_entry;
- + p4d_t *p4d, p4d_entry;
- + unsigned long next;
- +
- + if (pgd_none(*pgd)) {
- + pgd_entry = __pgd(_KERNPG_TABLE | __pa_nodebug(kasan_zero_p4d));
- + set_pgd(pgd, pgd_entry);
- + }
- +
- + p4d = early_p4d_offset(pgd, addr);
- + do {
- + next = p4d_addr_end(addr, end);
- +
- + if (!p4d_none(*p4d))
- + continue;
- +
- + p4d_entry = __p4d(_KERNPG_TABLE | __pa_nodebug(kasan_zero_pud));
- + set_p4d(p4d, p4d_entry);
- + } while (p4d++, addr = next, addr != end && p4d_none(*p4d));
- }
-
- static void __init kasan_map_early_shadow(pgd_t *pgd)
- {
- - int i;
- - unsigned long start = KASAN_SHADOW_START;
- + /* See comment in kasan_init() */
- + unsigned long addr = KASAN_SHADOW_START & PGDIR_MASK;
- unsigned long end = KASAN_SHADOW_END;
- + unsigned long next;
-
- - for (i = pgd_index(start); start < end; i++) {
- - switch (CONFIG_PGTABLE_LEVELS) {
- - case 4:
- - pgd[i] = __pgd(__pa_nodebug(kasan_zero_pud) |
- - _KERNPG_TABLE);
- - break;
- - case 5:
- - pgd[i] = __pgd(__pa_nodebug(kasan_zero_p4d) |
- - _KERNPG_TABLE);
- - break;
- - default:
- - BUILD_BUG();
- - }
- - start += PGDIR_SIZE;
- - }
- + pgd += pgd_index(addr);
- + do {
- + next = pgd_addr_end(addr, end);
- + kasan_early_p4d_populate(pgd, addr, next);
- + } while (pgd++, addr = next, addr != end);
- }
-
- #ifdef CONFIG_KASAN_INLINE
- @@ -101,7 +137,7 @@ void __init kasan_early_init(void)
- for (i = 0; i < PTRS_PER_PUD; i++)
- kasan_zero_pud[i] = __pud(pud_val);
-
- - for (i = 0; CONFIG_PGTABLE_LEVELS >= 5 && i < PTRS_PER_P4D; i++)
- + for (i = 0; IS_ENABLED(CONFIG_X86_5LEVEL) && i < PTRS_PER_P4D; i++)
- kasan_zero_p4d[i] = __p4d(p4d_val);
-
- kasan_map_early_shadow(early_top_pgt);
- @@ -117,12 +153,35 @@ void __init kasan_init(void)
- #endif
-
- memcpy(early_top_pgt, init_top_pgt, sizeof(early_top_pgt));
- +
- + /*
- + * We use the same shadow offset for 4- and 5-level paging to
- + * facilitate boot-time switching between paging modes.
- + * As result in 5-level paging mode KASAN_SHADOW_START and
- + * KASAN_SHADOW_END are not aligned to PGD boundary.
- + *
- + * KASAN_SHADOW_START doesn't share PGD with anything else.
- + * We claim whole PGD entry to make things easier.
- + *
- + * KASAN_SHADOW_END lands in the last PGD entry and it collides with
- + * bunch of things like kernel code, modules, EFI mapping, etc.
- + * We need to take extra steps to not overwrite them.
- + */
- + if (IS_ENABLED(CONFIG_X86_5LEVEL)) {
- + void *ptr;
- +
- + ptr = (void *)pgd_page_vaddr(*pgd_offset_k(KASAN_SHADOW_END));
- + memcpy(tmp_p4d_table, (void *)ptr, sizeof(tmp_p4d_table));
- + set_pgd(&early_top_pgt[pgd_index(KASAN_SHADOW_END)],
- + __pgd(__pa(tmp_p4d_table) | _KERNPG_TABLE));
- + }
- +
- load_cr3(early_top_pgt);
- __flush_tlb_all();
-
- - clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
- + clear_pgds(KASAN_SHADOW_START & PGDIR_MASK, KASAN_SHADOW_END);
-
- - kasan_populate_zero_shadow((void *)KASAN_SHADOW_START,
- + kasan_populate_zero_shadow((void *)(KASAN_SHADOW_START & PGDIR_MASK),
- kasan_mem_to_shadow((void *)PAGE_OFFSET));
-
- for (i = 0; i < E820_MAX_ENTRIES; i++) {
- diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
- index bf9f03740c30..67d07802ae95 100644
- --- a/arch/x86/Kconfig
- +++ b/arch/x86/Kconfig
- @@ -300,7 +300,6 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
- config KASAN_SHADOW_OFFSET
- hex
- depends on KASAN
- - default 0xdff8000000000000 if X86_5LEVEL
- default 0xdffffc0000000000
-
- config HAVE_INTEL_TXT
- --
- 2.14.2
|