aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Ryabinin <ryabinin.a.a@gmail.com>2015-10-12 11:52:58 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2015-10-12 12:46:36 -0400
commit39d114ddc68223022c12ae3a1573912bc4b585e5 (patch)
tree738d0566a0b66a8fec44b04fa1480f258e00a248
parentfd2203dd3556f6553231fa026060793e67a25ce6 (diff)
arm64: add KASAN support
This patch adds arch specific code for kernel address sanitizer (see Documentation/kasan.txt). 1/8 of kernel addresses reserved for shadow memory. There was no big enough hole for this, so virtual addresses for shadow were stolen from vmalloc area. At early boot stage the whole shadow region populated with just one physical page (kasan_zero_page). Later, this page reused as readonly zero shadow for some memory that KASan currently don't track (vmalloc). After mapping the physical memory, pages for shadow memory are allocated and mapped. Functions like memset/memmove/memcpy do a lot of memory accesses. If bad pointer passed to one of these function it is important to catch this. Compiler's instrumentation cannot do this since these functions are written in assembly. KASan replaces memory functions with manually instrumented variants. Original functions declared as weak symbols so strong definitions in mm/kasan/kasan.c could replace them. Original functions have aliases with '__' prefix in name, so we could call non-instrumented variant if needed. Some files built without kasan instrumentation (e.g. mm/slub.c). Original mem* function replaced (via #define) with prefixed variants to disable memory access checks for such files. Signed-off-by: Andrey Ryabinin <ryabinin.a.a@gmail.com> Tested-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/Makefile7
-rw-r--r--arch/arm64/include/asm/kasan.h36
-rw-r--r--arch/arm64/include/asm/pgtable.h7
-rw-r--r--arch/arm64/include/asm/string.h16
-rw-r--r--arch/arm64/kernel/Makefile2
-rw-r--r--arch/arm64/kernel/arm64ksyms.c3
-rw-r--r--arch/arm64/kernel/head.S3
-rw-r--r--arch/arm64/kernel/image.h6
-rw-r--r--arch/arm64/kernel/module.c16
-rw-r--r--arch/arm64/kernel/setup.c4
-rw-r--r--arch/arm64/lib/memcpy.S3
-rw-r--r--arch/arm64/lib/memmove.S7
-rw-r--r--arch/arm64/lib/memset.S3
-rw-r--r--arch/arm64/mm/Makefile3
-rw-r--r--arch/arm64/mm/kasan_init.c165
-rw-r--r--drivers/firmware/efi/Makefile8
-rw-r--r--scripts/Makefile.kasan4
18 files changed, 288 insertions, 6 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1b35bdbd5d74..2782c1189208 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -48,6 +48,7 @@ config ARM64
48 select HAVE_ARCH_AUDITSYSCALL 48 select HAVE_ARCH_AUDITSYSCALL
49 select HAVE_ARCH_BITREVERSE 49 select HAVE_ARCH_BITREVERSE
50 select HAVE_ARCH_JUMP_LABEL 50 select HAVE_ARCH_JUMP_LABEL
51 select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP
51 select HAVE_ARCH_KGDB 52 select HAVE_ARCH_KGDB
52 select HAVE_ARCH_SECCOMP_FILTER 53 select HAVE_ARCH_SECCOMP_FILTER
53 select HAVE_ARCH_TRACEHOOK 54 select HAVE_ARCH_TRACEHOOK
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index f9914d7c1bb0..f41c6761ec36 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -55,6 +55,13 @@ else
55TEXT_OFFSET := 0x00080000 55TEXT_OFFSET := 0x00080000
56endif 56endif
57 57
58# KASAN_SHADOW_OFFSET = VA_START + (1 << (VA_BITS - 3)) - (1 << 61)
59# in 32-bit arithmetic
60KASAN_SHADOW_OFFSET := $(shell printf "0x%08x00000000\n" $$(( \
61 (0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 32))) \
62 + (1 << ($(CONFIG_ARM64_VA_BITS) - 32 - 3)) \
63 - (1 << (64 - 32 - 3)) )) )
64
58export TEXT_OFFSET GZFLAGS 65export TEXT_OFFSET GZFLAGS
59 66
60core-y += arch/arm64/kernel/ arch/arm64/mm/ 67core-y += arch/arm64/kernel/ arch/arm64/mm/
diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h
new file mode 100644
index 000000000000..71dfe14acdca
--- /dev/null
+++ b/arch/arm64/include/asm/kasan.h
@@ -0,0 +1,36 @@
1#ifndef __ASM_KASAN_H
2#define __ASM_KASAN_H
3
4#ifndef __ASSEMBLY__
5
6#ifdef CONFIG_KASAN
7
8#include <asm/memory.h>
9
10/*
11 * KASAN_SHADOW_START: beginning of the kernel virtual addresses.
12 * KASAN_SHADOW_END: KASAN_SHADOW_START + 1/8 of kernel virtual addresses.
13 */
14#define KASAN_SHADOW_START (VA_START)
15#define KASAN_SHADOW_END (KASAN_SHADOW_START + (1UL << (VA_BITS - 3)))
16
17/*
18 * This value is used to map an address to the corresponding shadow
19 * address by the following formula:
20 * shadow_addr = (address >> 3) + KASAN_SHADOW_OFFSET;
21 *
22 * (1 << 61) shadow addresses - [KASAN_SHADOW_OFFSET,KASAN_SHADOW_END]
23 * cover all 64-bits of virtual addresses. So KASAN_SHADOW_OFFSET
24 * should satisfy the following equation:
25 * KASAN_SHADOW_OFFSET = KASAN_SHADOW_END - (1ULL << 61)
26 */
27#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_END - (1ULL << (64 - 3)))
28
29void kasan_init(void);
30
31#else
32static inline void kasan_init(void) { }
33#endif
34
35#endif
36#endif
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 3f481ef42c07..e3b515fbf0c2 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -41,7 +41,14 @@
41 * fixed mappings and modules 41 * fixed mappings and modules
42 */ 42 */
43#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE) 43#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
44
45#ifndef CONFIG_KASAN
44#define VMALLOC_START (VA_START) 46#define VMALLOC_START (VA_START)
47#else
48#include <asm/kasan.h>
49#define VMALLOC_START (KASAN_SHADOW_END + SZ_64K)
50#endif
51
45#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K) 52#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
46 53
47#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K)) 54#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K))
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 64d2d4884a9d..2eb714c4639f 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -36,17 +36,33 @@ extern __kernel_size_t strnlen(const char *, __kernel_size_t);
36 36
37#define __HAVE_ARCH_MEMCPY 37#define __HAVE_ARCH_MEMCPY
38extern void *memcpy(void *, const void *, __kernel_size_t); 38extern void *memcpy(void *, const void *, __kernel_size_t);
39extern void *__memcpy(void *, const void *, __kernel_size_t);
39 40
40#define __HAVE_ARCH_MEMMOVE 41#define __HAVE_ARCH_MEMMOVE
41extern void *memmove(void *, const void *, __kernel_size_t); 42extern void *memmove(void *, const void *, __kernel_size_t);
43extern void *__memmove(void *, const void *, __kernel_size_t);
42 44
43#define __HAVE_ARCH_MEMCHR 45#define __HAVE_ARCH_MEMCHR
44extern void *memchr(const void *, int, __kernel_size_t); 46extern void *memchr(const void *, int, __kernel_size_t);
45 47
46#define __HAVE_ARCH_MEMSET 48#define __HAVE_ARCH_MEMSET
47extern void *memset(void *, int, __kernel_size_t); 49extern void *memset(void *, int, __kernel_size_t);
50extern void *__memset(void *, int, __kernel_size_t);
48 51
49#define __HAVE_ARCH_MEMCMP 52#define __HAVE_ARCH_MEMCMP
50extern int memcmp(const void *, const void *, size_t); 53extern int memcmp(const void *, const void *, size_t);
51 54
55
56#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
57
58/*
59 * For files that are not instrumented (e.g. mm/slub.c) we
60 * should use not instrumented version of mem* functions.
61 */
62
63#define memcpy(dst, src, len) __memcpy(dst, src, len)
64#define memmove(dst, src, len) __memmove(dst, src, len)
65#define memset(s, c, n) __memset(s, c, n)
66#endif
67
52#endif 68#endif
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7b17f6245f1e..1b6bda2ff102 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,6 +7,8 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
7CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) 7CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
8CFLAGS_armv8_deprecated.o := -I$(src) 8CFLAGS_armv8_deprecated.o := -I$(src)
9 9
10KASAN_SANITIZE_efi-stub.o := n
11
10CFLAGS_REMOVE_ftrace.o = -pg 12CFLAGS_REMOVE_ftrace.o = -pg
11CFLAGS_REMOVE_insn.o = -pg 13CFLAGS_REMOVE_insn.o = -pg
12CFLAGS_REMOVE_return_address.o = -pg 14CFLAGS_REMOVE_return_address.o = -pg
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index a85843ddbde8..3b6d8cc9dfe0 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -51,6 +51,9 @@ EXPORT_SYMBOL(strnlen);
51EXPORT_SYMBOL(memset); 51EXPORT_SYMBOL(memset);
52EXPORT_SYMBOL(memcpy); 52EXPORT_SYMBOL(memcpy);
53EXPORT_SYMBOL(memmove); 53EXPORT_SYMBOL(memmove);
54EXPORT_SYMBOL(__memset);
55EXPORT_SYMBOL(__memcpy);
56EXPORT_SYMBOL(__memmove);
54EXPORT_SYMBOL(memchr); 57EXPORT_SYMBOL(memchr);
55EXPORT_SYMBOL(memcmp); 58EXPORT_SYMBOL(memcmp);
56 59
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 28a81e948df9..2a8c1d5b3fae 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -444,6 +444,9 @@ __mmap_switched:
444 str_l x21, __fdt_pointer, x5 // Save FDT pointer 444 str_l x21, __fdt_pointer, x5 // Save FDT pointer
445 str_l x24, memstart_addr, x6 // Save PHYS_OFFSET 445 str_l x24, memstart_addr, x6 // Save PHYS_OFFSET
446 mov x29, #0 446 mov x29, #0
447#ifdef CONFIG_KASAN
448 bl kasan_early_init
449#endif
447 b start_kernel 450 b start_kernel
448ENDPROC(__mmap_switched) 451ENDPROC(__mmap_switched)
449 452
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index e083af0dd546..6eb8fee93321 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -80,6 +80,12 @@ __efistub_strcmp = __pi_strcmp;
80__efistub_strncmp = __pi_strncmp; 80__efistub_strncmp = __pi_strncmp;
81__efistub___flush_dcache_area = __pi___flush_dcache_area; 81__efistub___flush_dcache_area = __pi___flush_dcache_area;
82 82
83#ifdef CONFIG_KASAN
84__efistub___memcpy = __pi_memcpy;
85__efistub___memmove = __pi_memmove;
86__efistub___memset = __pi_memset;
87#endif
88
83__efistub__text = _text; 89__efistub__text = _text;
84__efistub__end = _end; 90__efistub__end = _end;
85__efistub__edata = _edata; 91__efistub__edata = _edata;
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 876eb8df50bf..f4bc779e62e8 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -21,6 +21,7 @@
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/elf.h> 22#include <linux/elf.h>
23#include <linux/gfp.h> 23#include <linux/gfp.h>
24#include <linux/kasan.h>
24#include <linux/kernel.h> 25#include <linux/kernel.h>
25#include <linux/mm.h> 26#include <linux/mm.h>
26#include <linux/moduleloader.h> 27#include <linux/moduleloader.h>
@@ -34,9 +35,18 @@
34 35
35void *module_alloc(unsigned long size) 36void *module_alloc(unsigned long size)
36{ 37{
37 return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, 38 void *p;
38 GFP_KERNEL, PAGE_KERNEL_EXEC, 0, 39
39 NUMA_NO_NODE, __builtin_return_address(0)); 40 p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR, MODULES_END,
41 GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
42 NUMA_NO_NODE, __builtin_return_address(0));
43
44 if (p && (kasan_module_alloc(p, size) < 0)) {
45 vfree(p);
46 return NULL;
47 }
48
49 return p;
40} 50}
41 51
42enum aarch64_reloc_op { 52enum aarch64_reloc_op {
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 6bab21f84a9f..79df79a2ea61 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -54,6 +54,7 @@
54#include <asm/elf.h> 54#include <asm/elf.h>
55#include <asm/cpufeature.h> 55#include <asm/cpufeature.h>
56#include <asm/cpu_ops.h> 56#include <asm/cpu_ops.h>
57#include <asm/kasan.h>
57#include <asm/sections.h> 58#include <asm/sections.h>
58#include <asm/setup.h> 59#include <asm/setup.h>
59#include <asm/smp_plat.h> 60#include <asm/smp_plat.h>
@@ -434,6 +435,9 @@ void __init setup_arch(char **cmdline_p)
434 435
435 paging_init(); 436 paging_init();
436 relocate_initrd(); 437 relocate_initrd();
438
439 kasan_init();
440
437 request_standard_resources(); 441 request_standard_resources();
438 442
439 early_ioremap_reset(); 443 early_ioremap_reset();
diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S
index 36a6a62cf263..67613937711f 100644
--- a/arch/arm64/lib/memcpy.S
+++ b/arch/arm64/lib/memcpy.S
@@ -68,7 +68,10 @@
68 stp \ptr, \regB, [\regC], \val 68 stp \ptr, \regB, [\regC], \val
69 .endm 69 .endm
70 70
71 .weak memcpy
72ENTRY(__memcpy)
71ENTRY(memcpy) 73ENTRY(memcpy)
72#include "copy_template.S" 74#include "copy_template.S"
73 ret 75 ret
74ENDPIPROC(memcpy) 76ENDPIPROC(memcpy)
77ENDPROC(__memcpy)
diff --git a/arch/arm64/lib/memmove.S b/arch/arm64/lib/memmove.S
index 68e2f2035e23..a5a4459013b1 100644
--- a/arch/arm64/lib/memmove.S
+++ b/arch/arm64/lib/memmove.S
@@ -57,12 +57,14 @@ C_h .req x12
57D_l .req x13 57D_l .req x13
58D_h .req x14 58D_h .req x14
59 59
60 .weak memmove
61ENTRY(__memmove)
60ENTRY(memmove) 62ENTRY(memmove)
61 cmp dstin, src 63 cmp dstin, src
62 b.lo memcpy 64 b.lo __memcpy
63 add tmp1, src, count 65 add tmp1, src, count
64 cmp dstin, tmp1 66 cmp dstin, tmp1
65 b.hs memcpy /* No overlap. */ 67 b.hs __memcpy /* No overlap. */
66 68
67 add dst, dstin, count 69 add dst, dstin, count
68 add src, src, count 70 add src, src, count
@@ -195,3 +197,4 @@ ENTRY(memmove)
195 b.ne .Ltail63 197 b.ne .Ltail63
196 ret 198 ret
197ENDPIPROC(memmove) 199ENDPIPROC(memmove)
200ENDPROC(__memmove)
diff --git a/arch/arm64/lib/memset.S b/arch/arm64/lib/memset.S
index 29f405f08792..f2670a9f218c 100644
--- a/arch/arm64/lib/memset.S
+++ b/arch/arm64/lib/memset.S
@@ -54,6 +54,8 @@ dst .req x8
54tmp3w .req w9 54tmp3w .req w9
55tmp3 .req x9 55tmp3 .req x9
56 56
57 .weak memset
58ENTRY(__memset)
57ENTRY(memset) 59ENTRY(memset)
58 mov dst, dstin /* Preserve return value. */ 60 mov dst, dstin /* Preserve return value. */
59 and A_lw, val, #255 61 and A_lw, val, #255
@@ -214,3 +216,4 @@ ENTRY(memset)
214 b.ne .Ltail_maybe_long 216 b.ne .Ltail_maybe_long
215 ret 217 ret
216ENDPIPROC(memset) 218ENDPIPROC(memset)
219ENDPROC(__memset)
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
index 773d37a14039..57f57fde5722 100644
--- a/arch/arm64/mm/Makefile
+++ b/arch/arm64/mm/Makefile
@@ -4,3 +4,6 @@ obj-y := dma-mapping.o extable.o fault.o init.o \
4 context.o proc.o pageattr.o 4 context.o proc.o pageattr.o
5obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 5obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
6obj-$(CONFIG_ARM64_PTDUMP) += dump.o 6obj-$(CONFIG_ARM64_PTDUMP) += dump.o
7
8obj-$(CONFIG_KASAN) += kasan_init.o
9KASAN_SANITIZE_kasan_init.o := n
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
new file mode 100644
index 000000000000..b6a92f5dd568
--- /dev/null
+++ b/arch/arm64/mm/kasan_init.c
@@ -0,0 +1,165 @@
1/*
2 * This file contains kasan initialization code for ARM64.
3 *
4 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
5 * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12
13#define pr_fmt(fmt) "kasan: " fmt
14#include <linux/kasan.h>
15#include <linux/kernel.h>
16#include <linux/memblock.h>
17#include <linux/start_kernel.h>
18
19#include <asm/page.h>
20#include <asm/pgalloc.h>
21#include <asm/pgtable.h>
22#include <asm/tlbflush.h>
23
24static pgd_t tmp_pg_dir[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE);
25
26static void __init kasan_early_pte_populate(pmd_t *pmd, unsigned long addr,
27 unsigned long end)
28{
29 pte_t *pte;
30 unsigned long next;
31
32 if (pmd_none(*pmd))
33 pmd_populate_kernel(&init_mm, pmd, kasan_zero_pte);
34
35 pte = pte_offset_kernel(pmd, addr);
36 do {
37 next = addr + PAGE_SIZE;
38 set_pte(pte, pfn_pte(virt_to_pfn(kasan_zero_page),
39 PAGE_KERNEL));
40 } while (pte++, addr = next, addr != end && pte_none(*pte));
41}
42
43static void __init kasan_early_pmd_populate(pud_t *pud,
44 unsigned long addr,
45 unsigned long end)
46{
47 pmd_t *pmd;
48 unsigned long next;
49
50 if (pud_none(*pud))
51 pud_populate(&init_mm, pud, kasan_zero_pmd);
52
53 pmd = pmd_offset(pud, addr);
54 do {
55 next = pmd_addr_end(addr, end);
56 kasan_early_pte_populate(pmd, addr, next);
57 } while (pmd++, addr = next, addr != end && pmd_none(*pmd));
58}
59
60static void __init kasan_early_pud_populate(pgd_t *pgd,
61 unsigned long addr,
62 unsigned long end)
63{
64 pud_t *pud;
65 unsigned long next;
66
67 if (pgd_none(*pgd))
68 pgd_populate(&init_mm, pgd, kasan_zero_pud);
69
70 pud = pud_offset(pgd, addr);
71 do {
72 next = pud_addr_end(addr, end);
73 kasan_early_pmd_populate(pud, addr, next);
74 } while (pud++, addr = next, addr != end && pud_none(*pud));
75}
76
77static void __init kasan_map_early_shadow(void)
78{
79 unsigned long addr = KASAN_SHADOW_START;
80 unsigned long end = KASAN_SHADOW_END;
81 unsigned long next;
82 pgd_t *pgd;
83
84 pgd = pgd_offset_k(addr);
85 do {
86 next = pgd_addr_end(addr, end);
87 kasan_early_pud_populate(pgd, addr, next);
88 } while (pgd++, addr = next, addr != end);
89}
90
91void __init kasan_early_init(void)
92{
93 BUILD_BUG_ON(KASAN_SHADOW_OFFSET != KASAN_SHADOW_END - (1UL << 61));
94 BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE));
95 BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE));
96 kasan_map_early_shadow();
97}
98
99static void __init clear_pgds(unsigned long start,
100 unsigned long end)
101{
102 /*
103 * Remove references to kasan page tables from
104 * swapper_pg_dir. pgd_clear() can't be used
105 * here because it's nop on 2,3-level pagetable setups
106 */
107 for (; start < end; start += PGDIR_SIZE)
108 set_pgd(pgd_offset_k(start), __pgd(0));
109}
110
111static void __init cpu_set_ttbr1(unsigned long ttbr1)
112{
113 asm(
114 " msr ttbr1_el1, %0\n"
115 " isb"
116 :
117 : "r" (ttbr1));
118}
119
120void __init kasan_init(void)
121{
122 struct memblock_region *reg;
123
124 /*
125 * We are going to perform proper setup of shadow memory.
126 * At first we should unmap early shadow (clear_pgds() call bellow).
127 * However, instrumented code couldn't execute without shadow memory.
128 * tmp_pg_dir used to keep early shadow mapped until full shadow
129 * setup will be finished.
130 */
131 memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(tmp_pg_dir));
132 cpu_set_ttbr1(__pa(tmp_pg_dir));
133 flush_tlb_all();
134
135 clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
136
137 kasan_populate_zero_shadow((void *)KASAN_SHADOW_START,
138 kasan_mem_to_shadow((void *)MODULES_VADDR));
139
140 for_each_memblock(memory, reg) {
141 void *start = (void *)__phys_to_virt(reg->base);
142 void *end = (void *)__phys_to_virt(reg->base + reg->size);
143
144 if (start >= end)
145 break;
146
147 /*
148 * end + 1 here is intentional. We check several shadow bytes in
149 * advance to slightly speed up fastpath. In some rare cases
150 * we could cross boundary of mapped shadow, so we just map
151 * some more here.
152 */
153 vmemmap_populate((unsigned long)kasan_mem_to_shadow(start),
154 (unsigned long)kasan_mem_to_shadow(end) + 1,
155 pfn_to_nid(virt_to_pfn(start)));
156 }
157
158 memset(kasan_zero_page, 0, PAGE_SIZE);
159 cpu_set_ttbr1(__pa(swapper_pg_dir));
160 flush_tlb_all();
161
162 /* At this point kasan is fully initialized. Enable error messages */
163 init_task.kasan_depth = 0;
164 pr_info("KernelAddressSanitizer initialized\n");
165}
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 6fd3da938717..413fcf2970c0 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -1,6 +1,14 @@
1# 1#
2# Makefile for linux kernel 2# Makefile for linux kernel
3# 3#
4
5#
6# ARM64 maps efi runtime services in userspace addresses
7# which don't have KASAN shadow. So dereference of these addresses
8# in efi_call_virt() will cause crash if this code instrumented.
9#
10KASAN_SANITIZE_runtime-wrappers.o := n
11
4obj-$(CONFIG_EFI) += efi.o vars.o reboot.o 12obj-$(CONFIG_EFI) += efi.o vars.o reboot.o
5obj-$(CONFIG_EFI_VARS) += efivars.o 13obj-$(CONFIG_EFI_VARS) += efivars.o
6obj-$(CONFIG_EFI_ESRT) += esrt.o 14obj-$(CONFIG_EFI_ESRT) += esrt.o
diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan
index 3f874d24234f..37323b0df374 100644
--- a/scripts/Makefile.kasan
+++ b/scripts/Makefile.kasan
@@ -5,10 +5,12 @@ else
5 call_threshold := 0 5 call_threshold := 0
6endif 6endif
7 7
8KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET)
9
8CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address 10CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
9 11
10CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \ 12CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \
11 -fasan-shadow-offset=$(CONFIG_KASAN_SHADOW_OFFSET) \ 13 -fasan-shadow-offset=$(KASAN_SHADOW_OFFSET) \
12 --param asan-stack=1 --param asan-globals=1 \ 14 --param asan-stack=1 --param asan-globals=1 \
13 --param asan-instrumentation-with-call-threshold=$(call_threshold)) 15 --param asan-instrumentation-with-call-threshold=$(call_threshold))
14 16