fork: support VMAP_STACK with KASAN_VMALLOC
authorDaniel Axtens <dja@axtens.net>
Sun, 1 Dec 2019 01:54:57 +0000 (17:54 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 1 Dec 2019 20:59:05 +0000 (12:59 -0800)
Supporting VMAP_STACK with KASAN_VMALLOC is straightforward:

 - clear the shadow region of vmapped stacks when swapping them in
 - tweak Kconfig to allow VMAP_STACK to be turned on with KASAN

Link: http://lkml.kernel.org/r/20191031093909.9228-4-dja@axtens.net
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Reviewed-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/Kconfig
kernel/fork.c

index 17c42bc..ec07f9b 100644 (file)
@@ -843,16 +843,17 @@ config HAVE_ARCH_VMAP_STACK
 config VMAP_STACK
        default y
        bool "Use a virtually-mapped stack"
-       depends on HAVE_ARCH_VMAP_STACK && !KASAN
+       depends on HAVE_ARCH_VMAP_STACK
+       depends on !KASAN || KASAN_VMALLOC
        ---help---
          Enable this if you want the use virtually-mapped kernel stacks
          with guard pages.  This causes kernel stack overflows to be
          caught immediately rather than causing difficult-to-diagnose
          corruption.
 
-         This is presently incompatible with KASAN because KASAN expects
-         the stack to map directly to the KASAN shadow map using a formula
-         that is incorrect if the stack is in vmalloc space.
+         To use this with KASAN, the architecture must support backing
+         virtual mappings with real shadow memory, and KASAN_VMALLOC must
+         be enabled.
 
 config ARCH_OPTIONAL_KERNEL_RWX
        def_bool n
index 0f0bac8..21c6c1e 100644 (file)
@@ -93,6 +93,7 @@
 #include <linux/livepatch.h>
 #include <linux/thread_info.h>
 #include <linux/stackleak.h>
+#include <linux/kasan.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -223,6 +224,9 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
                if (!s)
                        continue;
 
+               /* Clear the KASAN shadow of the stack. */
+               kasan_unpoison_shadow(s->addr, THREAD_SIZE);
+
                /* Clear stale pointers from reused stack. */
                memset(s->addr, 0, THREAD_SIZE);