Commit c420f167 authored by Andrey Ryabinin's avatar Andrey Ryabinin Committed by Linus Torvalds

kasan: enable stack instrumentation

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: default avatarAndrey 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: default avatarAndrey 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 393f203f
#ifndef _ASM_X86_PAGE_64_DEFS_H #ifndef _ASM_X86_PAGE_64_DEFS_H
#define _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 THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#define CURRENT_MASK (~(THREAD_SIZE - 1)) #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 EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
#define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1) #define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1)
#define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER) #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 IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER)
#define DOUBLEFAULT_STACK 1 #define DOUBLEFAULT_STACK 1
......
...@@ -17,6 +17,8 @@ CFLAGS_REMOVE_early_printk.o = -pg ...@@ -17,6 +17,8 @@ CFLAGS_REMOVE_early_printk.o = -pg
endif endif
KASAN_SANITIZE_head$(BITS).o := n 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 CFLAGS_irq.o := -I$(src)/../include/asm/trace
......
...@@ -189,11 +189,18 @@ void __init kasan_init(void) ...@@ -189,11 +189,18 @@ void __init kasan_init(void)
if (map_range(&pfn_mapped[i])) if (map_range(&pfn_mapped[i]))
panic("kasan: unable to allocate shadow!"); panic("kasan: unable to allocate shadow!");
} }
populate_zero_shadow(kasan_mem_to_shadow((void *)PAGE_OFFSET + MAXMEM), 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); memset(kasan_zero_page, 0, PAGE_SIZE);
load_cr3(init_level4_pgt); load_cr3(init_level4_pgt);
init_task.kasan_depth = 0;
} }
...@@ -175,6 +175,13 @@ extern struct task_group root_task_group; ...@@ -175,6 +175,13 @@ extern struct task_group root_task_group;
# define INIT_NUMA_BALANCING(tsk) # define INIT_NUMA_BALANCING(tsk)
#endif #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 * INIT_TASK is used to set up the first task table, touch at
* your own risk!. Base=0, limit=0x1fffff (=2MB) * your own risk!. Base=0, limit=0x1fffff (=2MB)
...@@ -250,6 +257,7 @@ extern struct task_group root_task_group; ...@@ -250,6 +257,7 @@ extern struct task_group root_task_group;
INIT_RT_MUTEXES(tsk) \ INIT_RT_MUTEXES(tsk) \
INIT_VTIME(tsk) \ INIT_VTIME(tsk) \
INIT_NUMA_BALANCING(tsk) \ INIT_NUMA_BALANCING(tsk) \
INIT_KASAN(tsk) \
} }
......
...@@ -12,6 +12,15 @@ ...@@ -12,6 +12,15 @@
#define KASAN_KMALLOC_REDZONE 0xFC /* redzone inside slub object */ #define KASAN_KMALLOC_REDZONE 0xFC /* redzone inside slub object */
#define KASAN_KMALLOC_FREE 0xFB /* object was freed (kmem_cache_free/kfree) */ #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 { struct kasan_access_info {
const void *access_addr; const void *access_addr;
......
...@@ -64,6 +64,12 @@ static void print_error_description(struct kasan_access_info *info) ...@@ -64,6 +64,12 @@ static void print_error_description(struct kasan_access_info *info)
case 0 ... KASAN_SHADOW_SCALE_SIZE - 1: case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
bug_type = "out of bounds access"; bug_type = "out of bounds access";
break; 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", pr_err("BUG: KASan: %s in %pS at addr %p\n",
......
...@@ -9,6 +9,7 @@ CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address ...@@ -9,6 +9,7 @@ CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \ CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \
-fasan-shadow-offset=$(CONFIG_KASAN_SHADOW_OFFSET) \ -fasan-shadow-offset=$(CONFIG_KASAN_SHADOW_OFFSET) \
--param asan-stack=1 \
--param asan-instrumentation-with-call-threshold=$(call_threshold)) --param asan-instrumentation-with-call-threshold=$(call_threshold))
ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),) ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment