From: Patricia Alfonso <trishalfonso@google.com>
To: jdike@addtoit.com, richard@nod.at,
anton.ivanov@cambridgegreys.com, aryabinin@virtuozzo.com,
dvyukov@google.com, davidgow@google.com,
brendanhiggins@google.com
Cc: linux-um@lists.infradead.org, kasan-dev@googlegroups.com,
linux-kernel@vger.kernel.org,
Patricia Alfonso <trishalfonso@google.com>
Subject: [RFC PATCH] UML: add support for KASAN under x86_64
Date: Wed, 15 Jan 2020 10:28:16 -0800 [thread overview]
Message-ID: <20200115182816.33892-1-trishalfonso@google.com> (raw)
Make KASAN run on User Mode Linux on x86_64.
The location of the KASAN shadow memory, starting at
KASAN_SHADOW_OFFSET, can be configured using the
KASAN_SHADOW_OFFSET option. UML uses roughly 18TB of address
space, and KASAN requires 1/8th of this. For this reason, the default
location is 0x100000000000. There is usually enough free space at
this location; however, it is a config option so that it can be
easily changed if needed.
Functions that are used before KASAN is initialized are excluded from
instrumentation. The UML-specific KASAN initializer uses mmap to map
the roughly 2.25TB of shadow memory to the location defined by
KASAN_SHADOW_OFFSET and ensures that the address space used by the
kernel text and the vmalloc region is not poisoned at
initialization.
Signed-off-by: Patricia Alfonso <trishalfonso@google.com>
---
arch/um/Kconfig | 10 ++++++++++
arch/um/include/asm/dma.h | 1 +
arch/um/include/asm/kasan.h | 32 ++++++++++++++++++++++++++++++++
arch/um/kernel/Makefile | 4 ++++
arch/um/kernel/kasan_init_um.c | 20 ++++++++++++++++++++
arch/um/kernel/skas/Makefile | 6 ++++++
arch/um/kernel/um_arch.c | 3 +++
arch/um/os-Linux/mem.c | 18 ++++++++++++++++++
arch/um/os-Linux/user_syms.c | 4 ++--
arch/x86/um/Makefile | 3 ++-
arch/x86/um/vdso/Makefile | 3 +++
kernel/Makefile | 6 ++++++
lib/Makefile | 10 ++++++++++
13 files changed, 117 insertions(+), 3 deletions(-)
create mode 100644 arch/um/include/asm/kasan.h
create mode 100644 arch/um/kernel/kasan_init_um.c
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 6f0edd0c0220..99c68863e7e9 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -8,6 +8,7 @@ config UML
select ARCH_HAS_KCOV
select ARCH_NO_PREEMPT
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_ARCH_KASAN
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ASM_MODVERSIONS
select HAVE_UID16
@@ -198,6 +199,15 @@ config UML_TIME_TRAVEL_SUPPORT
It is safe to say Y, but you probably don't need this.
+config KASAN_SHADOW_OFFSET
+ hex
+ depends on KASAN
+ default 0x100000000000
+ help
+ This is the offset at which the ~2.25TB of shadow memory is
+ initialized and used by KASAN for memory debugging. The default
+ is 0x100000000000.
+
endmenu
source "arch/um/drivers/Kconfig"
diff --git a/arch/um/include/asm/dma.h b/arch/um/include/asm/dma.h
index fdc53642c718..8aafd60d62bb 100644
--- a/arch/um/include/asm/dma.h
+++ b/arch/um/include/asm/dma.h
@@ -5,6 +5,7 @@
#include <asm/io.h>
extern unsigned long uml_physmem;
+extern unsigned long long physmem_size;
#define MAX_DMA_ADDRESS (uml_physmem)
diff --git a/arch/um/include/asm/kasan.h b/arch/um/include/asm/kasan.h
new file mode 100644
index 000000000000..ca4c43a35d41
--- /dev/null
+++ b/arch/um/include/asm/kasan.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_UM_KASAN_H
+#define __ASM_UM_KASAN_H
+
+#include <linux/init.h>
+#include <linux/const.h>
+
+#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
+#ifdef CONFIG_X86_64
+#define KASAN_SHADOW_SIZE 0x100000000000UL
+#else
+#error "KASAN_SHADOW_SIZE is not defined in this sub-architecture"
+#endif
+
+// used in kasan_mem_to_shadow to divide by 8
+#define KASAN_SHADOW_SCALE_SHIFT 3
+
+#define KASAN_SHADOW_START (KASAN_SHADOW_OFFSET)
+#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
+
+#ifdef CONFIG_KASAN
+void kasan_init(void);
+void kasan_map_shadow(void);
+#else
+static inline void kasan_early_init(void) { }
+static inline void kasan_init(void) { }
+#endif /* CONFIG_KASAN */
+
+void kasan_map_memory(void *start, unsigned long len);
+void kasan_unpoison_shadow(const void *address, size_t size);
+
+#endif /* __ASM_UM_KASAN_H */
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 5aa882011e04..f783a7dd863c 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -8,6 +8,9 @@
# kernel.
KCOV_INSTRUMENT := n
+# Do not instrument on main.o
+KASAN_SANITIZE := n
+
CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \
-DELF_ARCH=$(LDS_ELF_ARCH) \
-DELF_FORMAT=$(LDS_ELF_FORMAT) \
@@ -24,6 +27,7 @@ obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
+obj-$(CONFIG_KASAN) += kasan_init_um.o
USER_OBJS := config.o
diff --git a/arch/um/kernel/kasan_init_um.c b/arch/um/kernel/kasan_init_um.c
new file mode 100644
index 000000000000..2e9a85216fb5
--- /dev/null
+++ b/arch/um/kernel/kasan_init_um.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <asm/kasan.h>
+#include <linux/sched.h>
+#include <linux/sched/task.h>
+#include <asm/dma.h>
+#include <as-layout.h>
+
+void kasan_init(void)
+{
+ kasan_map_memory((void *)KASAN_SHADOW_START, KASAN_SHADOW_SIZE);
+
+ // unpoison the kernel text which is form uml_physmem -> uml_reserved
+ kasan_unpoison_shadow((void *)uml_physmem, physmem_size);
+
+ // unpoison the vmalloc region, which is start_vm -> end_vm
+ kasan_unpoison_shadow((void *)start_vm, (end_vm - start_vm + 1));
+
+ init_task.kasan_depth = 0;
+ pr_info("KernelAddressSanitizer initialized\n");
+}
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index f3d494a4fd9b..d68f447274e5 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -5,6 +5,12 @@
obj-y := clone.o mmu.o process.o syscall.o uaccess.o
+ifdef CONFIG_UML
+# Do not instrument until after start_uml() because KASAN is not
+# initialized yet
+KASAN_SANITIZE := n
+endif
+
# clone.o is in the stub, so it can't be built with profiling
# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
# disable it
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 0f40eccbd759..73cd159d28e8 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -14,6 +14,7 @@
#include <linux/sched/task.h>
#include <linux/kmsg_dump.h>
+#include <asm/kasan.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/sections.h>
@@ -227,6 +228,8 @@ static struct notifier_block panic_exit_notifier = {
void uml_finishsetup(void)
{
+ kasan_init();
+
atomic_notifier_chain_register(&panic_notifier_list,
&panic_exit_notifier);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 3c1b77474d2d..ef282bacc58e 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -17,6 +17,24 @@
#include <init.h>
#include <os.h>
+/**
+ * kasan_map_memory() - maps memory from @start with a size of @len
+ * @start: the start address of the memory to be mapped
+ * @len: the length of the memory to be mapped
+ *
+ * This function is used to map shadow memory for KASAN in uml
+ */
+void kasan_map_memory(void *start, size_t len)
+{
+ if (mmap(start,
+ len,
+ PROT_READ|PROT_WRITE,
+ MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE,
+ -1,
+ 0) == MAP_FAILED)
+ os_info("Couldn't allocate shadow memory %s", strerror(errno));
+}
+
/* Set by make_tempfile() during early boot. */
static char *tempdir = NULL;
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 715594fe5719..cb667c9225ab 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -27,10 +27,10 @@ EXPORT_SYMBOL(strstr);
#ifndef __x86_64__
extern void *memcpy(void *, const void *, size_t);
EXPORT_SYMBOL(memcpy);
-#endif
-
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memset);
+#endif
+
EXPORT_SYMBOL(printf);
/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile
index 33c51c064c77..7dbd76c546fe 100644
--- a/arch/x86/um/Makefile
+++ b/arch/x86/um/Makefile
@@ -26,7 +26,8 @@ else
obj-y += syscalls_64.o vdso/
-subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../entry/thunk_64.o
+subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../entry/thunk_64.o \
+ ../lib/memmove_64.o ../lib/memset_64.o
endif
diff --git a/arch/x86/um/vdso/Makefile b/arch/x86/um/vdso/Makefile
index 0caddd6acb22..450efa0fb694 100644
--- a/arch/x86/um/vdso/Makefile
+++ b/arch/x86/um/vdso/Makefile
@@ -3,6 +3,9 @@
# Building vDSO images for x86.
#
+# do not instrument on vdso because KASAN is not compatible with user mode
+KASAN_SANITIZE := n
+
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT := n
diff --git a/kernel/Makefile b/kernel/Makefile
index f2cc0d118a0b..4fbb72cb253f 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -32,6 +32,12 @@ KCOV_INSTRUMENT_kcov.o := n
KASAN_SANITIZE_kcov.o := n
CFLAGS_kcov.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
+ifdef CONFIG_UML
+# Do not istrument kasan on panic because it can be called before KASAN
+# is initialized
+KASAN_SANITIZE_panic.o := n
+endif
+
# cond_syscall is currently not LTO compatible
CFLAGS_sys_ni.o = $(DISABLE_LTO)
diff --git a/lib/Makefile b/lib/Makefile
index 93217d44237f..e28dc5b06ae2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -17,6 +17,16 @@ KCOV_INSTRUMENT_list_debug.o := n
KCOV_INSTRUMENT_debugobjects.o := n
KCOV_INSTRUMENT_dynamic_debug.o := n
+# Don't sanatize vsprintf or string functions in UM because they are used
+# before KASAN is initialized from cmdline parsing cmdline and kstrtox are
+# also called during uml initialization before KASAN is instrumented
+ifdef CONFIG_UML
+KASAN_SANITIZE_vsprintf.o := n
+KASAN_SANITIZE_string.o := n
+KASAN_SANITIZE_cmdline.o := n
+KASAN_SANITIZE_kstrtox.o := n
+endif
+
# Early boot use of cmdline, don't instrument it
ifdef CONFIG_AMD_MEM_ENCRYPT
KASAN_SANITIZE_string.o := n
--
2.25.0.rc1.283.g88dfdc4193-goog
next reply other threads:[~2020-01-15 18:28 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-15 18:28 Patricia Alfonso [this message]
2020-01-15 18:48 ` [RFC PATCH] UML: add support for KASAN under x86_64 Johannes Berg
2020-01-15 22:56 ` Patricia Alfonso
2020-01-16 7:57 ` Johannes Berg
2020-01-16 8:03 ` Johannes Berg
2020-01-16 9:18 ` Dmitry Vyukov
2020-01-16 9:20 ` Johannes Berg
2020-01-16 9:23 ` Dmitry Vyukov
2020-01-17 9:59 ` Dmitry Vyukov
2020-01-17 10:03 ` Dmitry Vyukov
2020-01-17 10:05 ` Dmitry Vyukov
2020-02-06 18:33 ` Patricia Alfonso
2020-02-06 18:21 ` Patricia Alfonso
2020-02-06 19:14 ` Johannes Berg
2020-01-16 8:24 ` Dmitry Vyukov
2020-01-16 8:44 ` Dmitry Vyukov
2020-02-11 23:48 ` Patricia Alfonso
2020-02-12 6:23 ` Dmitry Vyukov
2020-01-16 8:50 ` Dmitry Vyukov
2020-01-16 8:52 ` Dmitry Vyukov
2020-02-12 0:19 ` Patricia Alfonso
2020-02-12 6:24 ` Dmitry Vyukov
2020-02-12 22:25 ` Patricia Alfonso
2020-02-13 5:39 ` Dmitry Vyukov
2020-02-13 22:55 ` Patricia Alfonso
2020-01-16 9:09 ` Dmitry Vyukov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200115182816.33892-1-trishalfonso@google.com \
--to=trishalfonso@google.com \
--cc=anton.ivanov@cambridgegreys.com \
--cc=aryabinin@virtuozzo.com \
--cc=brendanhiggins@google.com \
--cc=davidgow@google.com \
--cc=dvyukov@google.com \
--cc=jdike@addtoit.com \
--cc=kasan-dev@googlegroups.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-um@lists.infradead.org \
--cc=richard@nod.at \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).