aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorAndrey Ryabinin <a.ryabinin@samsung.com>2015-02-13 17:39:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-14 00:21:41 -0500
commitef7f0d6a6ca8c9e4b27d78895af86c2fbfaeedb2 (patch)
treeac747fe9eb870b1c501f0f13063b092bd1ff0e97 /arch/x86/kernel
parent786a8959912eb94fc2381c2ae487a96ce55dabca (diff)
x86_64: add KASan support
This patch adds arch specific code for kernel address sanitizer. 16TB of virtual addressed used for shadow memory. It's located in range [ffffec0000000000 - fffffc0000000000] between vmemmap and %esp fixup stacks. At early stage we map whole shadow region with zero page. Latter, after pages mapped to direct mapping address range we unmap zero pages from corresponding shadow (see kasan_map_shadow()) and allocate and map a real shadow memory reusing vmemmap_populate() function. Also replace __pa with __pa_nodebug before shadow initialized. __pa with CONFIG_DEBUG_VIRTUAL=y make external function call (__phys_addr) __phys_addr is instrumented, so __asan_load could be called before shadow area initialized. Signed-off-by: Andrey Ryabinin <a.ryabinin@samsung.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Konstantin Serebryany <kcc@google.com> Cc: Dmitry Chernenkov <dmitryc@google.com> Signed-off-by: Andrey Konovalov <adech.fo@gmail.com> Cc: Yuri Gribov <tetra2005@gmail.com> Cc: Konstantin Khlebnikov <koct9i@gmail.com> Cc: Sasha Levin <sasha.levin@oracle.com> Cc: Christoph Lameter <cl@linux.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: David Rientjes <rientjes@google.com> Cc: Jim Davis <jim.epost@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/dumpstack.c5
-rw-r--r--arch/x86/kernel/head64.c9
-rw-r--r--arch/x86/kernel/head_64.S30
-rw-r--r--arch/x86/kernel/setup.c3
5 files changed, 46 insertions, 3 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 732223496968..b13b70634124 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -16,6 +16,8 @@ CFLAGS_REMOVE_ftrace.o = -pg
16CFLAGS_REMOVE_early_printk.o = -pg 16CFLAGS_REMOVE_early_printk.o = -pg
17endif 17endif
18 18
19KASAN_SANITIZE_head$(BITS).o := n
20
19CFLAGS_irq.o := -I$(src)/../include/asm/trace 21CFLAGS_irq.o := -I$(src)/../include/asm/trace
20 22
21obj-y := process_$(BITS).o signal.o entry_$(BITS).o 23obj-y := process_$(BITS).o signal.o entry_$(BITS).o
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index b74ebc7c4402..cf3df1d8d039 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -265,7 +265,10 @@ int __die(const char *str, struct pt_regs *regs, long err)
265 printk("SMP "); 265 printk("SMP ");
266#endif 266#endif
267#ifdef CONFIG_DEBUG_PAGEALLOC 267#ifdef CONFIG_DEBUG_PAGEALLOC
268 printk("DEBUG_PAGEALLOC"); 268 printk("DEBUG_PAGEALLOC ");
269#endif
270#ifdef CONFIG_KASAN
271 printk("KASAN");
269#endif 272#endif
270 printk("\n"); 273 printk("\n");
271 if (notify_die(DIE_OOPS, str, regs, err, 274 if (notify_die(DIE_OOPS, str, regs, err,
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index eda1a865641e..efcddfaf05f9 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -27,6 +27,7 @@
27#include <asm/bios_ebda.h> 27#include <asm/bios_ebda.h>
28#include <asm/bootparam_utils.h> 28#include <asm/bootparam_utils.h>
29#include <asm/microcode.h> 29#include <asm/microcode.h>
30#include <asm/kasan.h>
30 31
31/* 32/*
32 * Manage page tables very early on. 33 * Manage page tables very early on.
@@ -46,7 +47,7 @@ static void __init reset_early_page_tables(void)
46 47
47 next_early_pgt = 0; 48 next_early_pgt = 0;
48 49
49 write_cr3(__pa(early_level4_pgt)); 50 write_cr3(__pa_nodebug(early_level4_pgt));
50} 51}
51 52
52/* Create a new PMD entry */ 53/* Create a new PMD entry */
@@ -59,7 +60,7 @@ int __init early_make_pgtable(unsigned long address)
59 pmdval_t pmd, *pmd_p; 60 pmdval_t pmd, *pmd_p;
60 61
61 /* Invalid address or early pgt is done ? */ 62 /* Invalid address or early pgt is done ? */
62 if (physaddr >= MAXMEM || read_cr3() != __pa(early_level4_pgt)) 63 if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
63 return -1; 64 return -1;
64 65
65again: 66again:
@@ -158,6 +159,8 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
158 /* Kill off the identity-map trampoline */ 159 /* Kill off the identity-map trampoline */
159 reset_early_page_tables(); 160 reset_early_page_tables();
160 161
162 kasan_map_early_shadow(early_level4_pgt);
163
161 /* clear bss before set_intr_gate with early_idt_handler */ 164 /* clear bss before set_intr_gate with early_idt_handler */
162 clear_bss(); 165 clear_bss();
163 166
@@ -179,6 +182,8 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
179 /* set init_level4_pgt kernel high mapping*/ 182 /* set init_level4_pgt kernel high mapping*/
180 init_level4_pgt[511] = early_level4_pgt[511]; 183 init_level4_pgt[511] = early_level4_pgt[511];
181 184
185 kasan_map_early_shadow(init_level4_pgt);
186
182 x86_64_start_reservations(real_mode_data); 187 x86_64_start_reservations(real_mode_data);
183} 188}
184 189
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index a468c0a65c42..6fd514d9f69a 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -514,8 +514,38 @@ ENTRY(phys_base)
514 /* This must match the first entry in level2_kernel_pgt */ 514 /* This must match the first entry in level2_kernel_pgt */
515 .quad 0x0000000000000000 515 .quad 0x0000000000000000
516 516
517#ifdef CONFIG_KASAN
518#define FILL(VAL, COUNT) \
519 .rept (COUNT) ; \
520 .quad (VAL) ; \
521 .endr
522
523NEXT_PAGE(kasan_zero_pte)
524 FILL(kasan_zero_page - __START_KERNEL_map + _KERNPG_TABLE, 512)
525NEXT_PAGE(kasan_zero_pmd)
526 FILL(kasan_zero_pte - __START_KERNEL_map + _KERNPG_TABLE, 512)
527NEXT_PAGE(kasan_zero_pud)
528 FILL(kasan_zero_pmd - __START_KERNEL_map + _KERNPG_TABLE, 512)
529
530#undef FILL
531#endif
532
533
517#include "../../x86/xen/xen-head.S" 534#include "../../x86/xen/xen-head.S"
518 535
519 __PAGE_ALIGNED_BSS 536 __PAGE_ALIGNED_BSS
520NEXT_PAGE(empty_zero_page) 537NEXT_PAGE(empty_zero_page)
521 .skip PAGE_SIZE 538 .skip PAGE_SIZE
539
540#ifdef CONFIG_KASAN
541/*
542 * This page used as early shadow. We don't use empty_zero_page
543 * at early stages, stack instrumentation could write some garbage
544 * to this page.
545 * Latter we reuse it as zero shadow for large ranges of memory
546 * that allowed to access, but not instrumented by kasan
547 * (vmalloc/vmemmap ...).
548 */
549NEXT_PAGE(kasan_zero_page)
550 .skip PAGE_SIZE
551#endif
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c4648adadd7d..27d200929864 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -89,6 +89,7 @@
89#include <asm/cacheflush.h> 89#include <asm/cacheflush.h>
90#include <asm/processor.h> 90#include <asm/processor.h>
91#include <asm/bugs.h> 91#include <asm/bugs.h>
92#include <asm/kasan.h>
92 93
93#include <asm/vsyscall.h> 94#include <asm/vsyscall.h>
94#include <asm/cpu.h> 95#include <asm/cpu.h>
@@ -1174,6 +1175,8 @@ void __init setup_arch(char **cmdline_p)
1174 1175
1175 x86_init.paging.pagetable_init(); 1176 x86_init.paging.pagetable_init();
1176 1177
1178 kasan_init();
1179
1177 if (boot_cpu_data.cpuid_level >= 0) { 1180 if (boot_cpu_data.cpuid_level >= 0) {
1178 /* A CPU has %cr4 if and only if it has CPUID */ 1181 /* A CPU has %cr4 if and only if it has CPUID */
1179 mmu_cr4_features = read_cr4(); 1182 mmu_cr4_features = read_cr4();