mirror of
https://github.com/lkl/linux.git
synced 2025-12-20 00:23:14 +09:00
lkl: add KASAN support
To enable KASAN support the kasan=yes parameters should be passed to the host build, e.g.: make -C tools/lkl kasan=yes Signed-off-by: Eugene Rodionov <rodionov@google.com> Signed-off-by: Octavian Purdila <tavip@google.com>
This commit is contained in:
committed by
Octavian Purdila
parent
7deea5c421
commit
facd006081
@@ -40,6 +40,7 @@ config LKL
|
|||||||
select UACCESS_MEMCPY
|
select UACCESS_MEMCPY
|
||||||
select GENERIC_STRNCPY_FROM_USER
|
select GENERIC_STRNCPY_FROM_USER
|
||||||
select GENERIC_STRNLEN_USER
|
select GENERIC_STRNLEN_USER
|
||||||
|
select HAVE_ARCH_KASAN
|
||||||
|
|
||||||
config OUTPUT_FORMAT
|
config OUTPUT_FORMAT
|
||||||
string "Output format"
|
string "Output format"
|
||||||
@@ -105,3 +106,13 @@ config RAID6_PQ_BENCHMARK
|
|||||||
config STACKTRACE_SUPPORT
|
config STACKTRACE_SUPPORT
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
|
if KASAN
|
||||||
|
config KASAN_SHADOW_OFFSET
|
||||||
|
hex "KASAN shadow offset"
|
||||||
|
default "0"
|
||||||
|
|
||||||
|
config KASAN_SHADOW_SIZE
|
||||||
|
hex "KASAN shadow size"
|
||||||
|
default "0"
|
||||||
|
endif
|
||||||
|
|
||||||
|
|||||||
36
arch/lkl/include/asm/kasan.h
Normal file
36
arch/lkl/include/asm/kasan.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef _ASM_LKL_KASAN_H
|
||||||
|
#define _ASM_LKL_KASAN_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_KASAN
|
||||||
|
#include <linux/const.h>
|
||||||
|
#include <linux/pgtable.h>
|
||||||
|
|
||||||
|
#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
|
||||||
|
#define KASAN_SHADOW_SIZE _AC(CONFIG_KASAN_SHADOW_SIZE, UL)
|
||||||
|
|
||||||
|
#define KASAN_SHADOW_SCALE_SHIFT 3
|
||||||
|
|
||||||
|
#define KASAN_SHADOW_START KASAN_SHADOW_OFFSET
|
||||||
|
#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
|
||||||
|
|
||||||
|
extern int kasan_init(void);
|
||||||
|
extern int kasan_cleanup(void);
|
||||||
|
extern void kasan_unpoison_stack(void);
|
||||||
|
#else
|
||||||
|
static inline int kasan_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int kasan_cleanup(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void kasan_unpoison_stack(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
#ifndef _LKL_PGTABLE_H
|
#ifndef _LKL_PGTABLE_H
|
||||||
#define _LKL_PGTABLE_H
|
#define _LKL_PGTABLE_H
|
||||||
|
|
||||||
#include <asm-generic/pgtable-nopud.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
|
* (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <asm/processor.h>
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
#include <asm-generic/pgtable-nopud.h>
|
||||||
|
#include <asm/processor.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#define pgd_present(pgd) (1)
|
#define pgd_present(pgd) (1)
|
||||||
@@ -51,4 +49,7 @@ extern void *empty_zero_page;
|
|||||||
#define KMAP_START 0
|
#define KMAP_START 0
|
||||||
#define KMAP_END 0xffffffff
|
#define KMAP_END 0xffffffff
|
||||||
|
|
||||||
|
#define PTRS_PER_PTE 0
|
||||||
|
#define PTRS_PER_PMD 0
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define _ASM_LKL_SCHED_H
|
#define _ASM_LKL_SCHED_H
|
||||||
|
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <asm/kasan.h>
|
||||||
#include <uapi/asm/host_ops.h>
|
#include <uapi/asm/host_ops.h>
|
||||||
|
|
||||||
static inline void thread_sched_jb(void)
|
static inline void thread_sched_jb(void)
|
||||||
@@ -11,6 +12,11 @@ static inline void thread_sched_jb(void)
|
|||||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
lkl_ops->jmp_buf_set(¤t_thread_info()->sched_jb,
|
lkl_ops->jmp_buf_set(¤t_thread_info()->sched_jb,
|
||||||
schedule);
|
schedule);
|
||||||
|
/*
|
||||||
|
* The previous call to setjmp/longjmp won't unwind the stack
|
||||||
|
* and, as a result, shadow memory will remain poisoned.
|
||||||
|
*/
|
||||||
|
kasan_unpoison_stack();
|
||||||
} else {
|
} else {
|
||||||
lkl_bug("thread_sched_jb() can be used only for host task");
|
lkl_bug("thread_sched_jb() can be used only for host task");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
extra-y := vmlinux.lds
|
extra-y := vmlinux.lds
|
||||||
|
|
||||||
|
KASAN_SANITIZE_init.o := n
|
||||||
|
KASAN_SANITIZE_stacktrace.o := n
|
||||||
|
|
||||||
obj-y = setup.o threads.o irq.o time.o syscalls.o misc.o console.o \
|
obj-y = setup.o threads.o irq.o time.o syscalls.o misc.o console.o \
|
||||||
syscalls_32.o cpu.o init.o stacktrace.o
|
syscalls_32.o cpu.o init.o stacktrace.o
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
#include <asm/host_ops.h>
|
#include <asm/host_ops.h>
|
||||||
|
#include <asm/kasan.h>
|
||||||
|
|
||||||
int lkl_init(struct lkl_host_operations *ops)
|
int lkl_init(struct lkl_host_operations *ops)
|
||||||
{
|
{
|
||||||
lkl_ops = ops;
|
lkl_ops = ops;
|
||||||
|
|
||||||
|
return kasan_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void lkl_cleanup(void)
|
void lkl_cleanup(void)
|
||||||
{
|
{
|
||||||
|
if (kasan_cleanup() < 0)
|
||||||
|
lkl_printf("kasan: failed to cleanup\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,8 +111,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
|||||||
lkl_ops->sem_down(_prev->sched_sem);
|
lkl_ops->sem_down(_prev->sched_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_prev->dead)
|
if (_prev->dead) {
|
||||||
|
kasan_unpoison_stack();
|
||||||
lkl_ops->thread_exit();
|
lkl_ops->thread_exit();
|
||||||
|
}
|
||||||
|
|
||||||
return abs_prev;
|
return abs_prev;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
|
||||||
|
KASAN_SANITIZE_kasan.o := n
|
||||||
|
|
||||||
obj-y = bootmem.o
|
obj-y = bootmem.o
|
||||||
|
obj-$(CONFIG_KASAN) += kasan.o
|
||||||
|
|||||||
38
arch/lkl/mm/kasan.c
Normal file
38
arch/lkl/mm/kasan.c
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#include <linux/init_task.h>
|
||||||
|
#include <linux/kasan.h>
|
||||||
|
#include <asm/host_ops.h>
|
||||||
|
|
||||||
|
void kasan_unpoison_stack(void)
|
||||||
|
{
|
||||||
|
void *stack = NULL;
|
||||||
|
unsigned long stack_size;
|
||||||
|
|
||||||
|
if (lkl_ops->thread_stack)
|
||||||
|
stack = lkl_ops->thread_stack(&stack_size);
|
||||||
|
|
||||||
|
if (stack)
|
||||||
|
kasan_unpoison_range(stack, stack_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int kasan_cleanup(void)
|
||||||
|
{
|
||||||
|
return lkl_ops->munmap((void *)KASAN_SHADOW_OFFSET, KASAN_SHADOW_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int kasan_init(void)
|
||||||
|
{
|
||||||
|
void *offset = (void *)KASAN_SHADOW_OFFSET;
|
||||||
|
int prot = LKL_PROT_READ | LKL_PROT_WRITE;
|
||||||
|
|
||||||
|
/* reserve address range for KASAN shadow memory */
|
||||||
|
if (lkl_ops->mmap(offset, KASAN_SHADOW_SIZE, prot) != offset) {
|
||||||
|
lkl_printf("kasan: failed to map shadow memory\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_task.kasan_depth = 0;
|
||||||
|
pr_info("KernelAddressSanitizer initialized\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
POSIX_HOSTS=elf64 elf32
|
POSIX_HOSTS=elf64 elf32
|
||||||
|
KASAN_HOSTS=elf64-x86-64
|
||||||
NT_HOSTS=pe
|
NT_HOSTS=pe
|
||||||
|
|
||||||
define set_autoconf_var
|
define set_autoconf_var
|
||||||
@@ -117,6 +118,22 @@ define 64bit_host
|
|||||||
$(call set_kernel_config,64BIT,y)
|
$(call set_kernel_config,64BIT,y)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define kasan_x86_64
|
||||||
|
$(call set_autoconf_var,KASAN_SHADOW_OFFSET,0x0000200000000000)
|
||||||
|
$(call set_kernel_config,KASAN_SHADOW_OFFSET,0x0000200000000000)
|
||||||
|
$(call set_autoconf_var,KASAN_SHADOW_SIZE,0x0000100000000000)
|
||||||
|
$(call set_kernel_config,KASAN_SHADOW_SIZE,0x0000100000000000)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define kasan_enable
|
||||||
|
$(call set_autoconf_var,KASAN,y)
|
||||||
|
$(call set_kernel_config,KASAN,y)
|
||||||
|
# default is 20 which should be 1MB but observed 8MB of reserved
|
||||||
|
# memory - half of what we use
|
||||||
|
$(call set_kernel_config,STACK_HASH_ORDER,12)
|
||||||
|
$(if $(filter $(1),elf64-x86-64),$(call kasan_x86_64))
|
||||||
|
endef
|
||||||
|
|
||||||
define do_autoconf
|
define do_autoconf
|
||||||
export CROSS_COMPILE := $(CROSS_COMPILE)
|
export CROSS_COMPILE := $(CROSS_COMPILE)
|
||||||
export CC := $(CROSS_COMPILE)gcc
|
export CC := $(CROSS_COMPILE)gcc
|
||||||
@@ -131,6 +148,7 @@ define do_autoconf
|
|||||||
$(if $(filter $(EXEC_FMT),elf64-s390),$(call s390_host))
|
$(if $(filter $(EXEC_FMT),elf64-s390),$(call s390_host))
|
||||||
$(if $(filter $(EXEC_FMT),$(POSIX_HOSTS)),$(call posix_host,$(LD_FMT)))
|
$(if $(filter $(EXEC_FMT),$(POSIX_HOSTS)),$(call posix_host,$(LD_FMT)))
|
||||||
$(if $(filter $(EXEC_FMT),$(NT_HOSTS)),$(call nt_host,$(LD_FMT)))
|
$(if $(filter $(EXEC_FMT),$(NT_HOSTS)),$(call nt_host,$(LD_FMT)))
|
||||||
|
$(if $(and $(filter yes,$(kasan)),$(filter $(LD_FMT),$(KASAN_HOSTS))),$(call kasan_enable,$(LD_FMT)))
|
||||||
endef
|
endef
|
||||||
|
|
||||||
export do_autoconf
|
export do_autoconf
|
||||||
|
|||||||
Reference in New Issue
Block a user