kasan: enable stack instrumentation
authorAndrey Ryabinin <a.ryabinin@samsung.com>
Fri, 13 Feb 2015 22:39:59 +0000 (14:39 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 14 Feb 2015 05:21:41 +0000 (21:21 -0800)
Stack instrumentation allows to detect out of bounds memory accesses for
variables allocated on stack.  Compiler adds redzones around every
variable on stack and poisons redzones in function's prologue.

Such approach significantly increases stack usage, so all in-kernel stacks
size were doubled.

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>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/x86/include/asm/page_64_types.h
arch/x86/kernel/Makefile
arch/x86/mm/kasan_init_64.c
include/linux/init_task.h
mm/kasan/kasan.h
mm/kasan/report.c
scripts/Makefile.kasan

index 75450b2c7be48393607da8a5fdf050e663eb48c8..4edd53b79a81aa3054df42137dbfc854ffe124ff 100644 (file)
@@ -1,17 +1,23 @@
 #ifndef _ASM_X86_PAGE_64_DEFS_H
 #define _ASM_X86_PAGE_64_DEFS_H
 
-#define THREAD_SIZE_ORDER      2
+#ifdef CONFIG_KASAN
+#define KASAN_STACK_ORDER 1
+#else
+#define KASAN_STACK_ORDER 0
+#endif
+
+#define THREAD_SIZE_ORDER      (2 + KASAN_STACK_ORDER)
 #define THREAD_SIZE  (PAGE_SIZE << THREAD_SIZE_ORDER)
 #define CURRENT_MASK (~(THREAD_SIZE - 1))
 
-#define EXCEPTION_STACK_ORDER 0
+#define EXCEPTION_STACK_ORDER (0 + KASAN_STACK_ORDER)
 #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
 
 #define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1)
 #define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER)
 
-#define IRQ_STACK_ORDER 2
+#define IRQ_STACK_ORDER (2 + KASAN_STACK_ORDER)
 #define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER)
 
 #define DOUBLEFAULT_STACK 1
index b13b7063412403aaded0a23ceed4e05d109b44f2..cdb1b70ddad0f026cbe42800571d0869211bf6f5 100644 (file)
@@ -17,6 +17,8 @@ CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
 KASAN_SANITIZE_head$(BITS).o := n
+KASAN_SANITIZE_dumpstack.o := n
+KASAN_SANITIZE_dumpstack_$(BITS).o := n
 
 CFLAGS_irq.o := -I$(src)/../include/asm/trace
 
index 3e4d9a1a39fa68cc947a9ebd54bd92aaf7cbd148..53508708b7aa22af7dd62eec1e0544102f08d2a7 100644 (file)
@@ -189,11 +189,18 @@ void __init kasan_init(void)
                if (map_range(&pfn_mapped[i]))
                        panic("kasan: unable to allocate shadow!");
        }
-
        populate_zero_shadow(kasan_mem_to_shadow((void *)PAGE_OFFSET + MAXMEM),
-                               (void *)KASAN_SHADOW_END);
+                       kasan_mem_to_shadow((void *)__START_KERNEL_map));
+
+       vmemmap_populate((unsigned long)kasan_mem_to_shadow(_stext),
+                       (unsigned long)kasan_mem_to_shadow(_end),
+                       NUMA_NO_NODE);
+
+       populate_zero_shadow(kasan_mem_to_shadow((void *)MODULES_VADDR),
+                       (void *)KASAN_SHADOW_END);
 
        memset(kasan_zero_page, 0, PAGE_SIZE);
 
        load_cr3(init_level4_pgt);
+       init_task.kasan_depth = 0;
 }
index d3d43ecf148cd96a22366e8569231c4df0ddbeb8..696d22312b3199ed2f515240111a669a35d48934 100644 (file)
@@ -175,6 +175,13 @@ extern struct task_group root_task_group;
 # define INIT_NUMA_BALANCING(tsk)
 #endif
 
+#ifdef CONFIG_KASAN
+# define INIT_KASAN(tsk)                                               \
+       .kasan_depth = 1,
+#else
+# define INIT_KASAN(tsk)
+#endif
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -250,6 +257,7 @@ extern struct task_group root_task_group;
        INIT_RT_MUTEXES(tsk)                                            \
        INIT_VTIME(tsk)                                                 \
        INIT_NUMA_BALANCING(tsk)                                        \
+       INIT_KASAN(tsk)                                                 \
 }
 
 
index 5b052ab40cf9f780ac64bd74841dd7745a3e613b..1fcc1d81a9cf5a6cf40a71f225fe0f631795dfb7 100644 (file)
 #define KASAN_KMALLOC_REDZONE   0xFC  /* redzone inside slub object */
 #define KASAN_KMALLOC_FREE      0xFB  /* object was freed (kmem_cache_free/kfree) */
 
+/*
+ * Stack redzone shadow values
+ * (Those are compiler's ABI, don't change them)
+ */
+#define KASAN_STACK_LEFT        0xF1
+#define KASAN_STACK_MID         0xF2
+#define KASAN_STACK_RIGHT       0xF3
+#define KASAN_STACK_PARTIAL     0xF4
+
 
 struct kasan_access_info {
        const void *access_addr;
index 2760edb4d0a8a5921cfdd7f5681a51745befcf5a..866732ef3db332d946c637d79ccb8e45d6ac209a 100644 (file)
@@ -64,6 +64,12 @@ static void print_error_description(struct kasan_access_info *info)
        case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
                bug_type = "out of bounds access";
                break;
+       case KASAN_STACK_LEFT:
+       case KASAN_STACK_MID:
+       case KASAN_STACK_RIGHT:
+       case KASAN_STACK_PARTIAL:
+               bug_type = "out of bounds on stack";
+               break;
        }
 
        pr_err("BUG: KASan: %s in %pS at addr %p\n",
index 7acd6faa033557c781f972ded3ad88740693b958..2163b8cc446ebdcbe61a6559bd8719d17c6d5c98 100644 (file)
@@ -9,6 +9,7 @@ CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
 
 CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \
                -fasan-shadow-offset=$(CONFIG_KASAN_SHADOW_OFFSET) \
+               --param asan-stack=1 \
                --param asan-instrumentation-with-call-threshold=$(call_threshold))
 
 ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),)