diff options
author | Harshit Sharma <harshitsharmajs@gmail.com> | 2020-07-20 00:21:05 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2020-08-21 07:41:19 +0000 |
commit | a6ebe08333dcc6c263b6bb8936d4883663c63798 (patch) | |
tree | 8f06ee5f79cf4efb54f189c17512a6120d2edd40 | |
parent | 9c88fb8df0005dc60e6c62778b4f16313cb3308e (diff) |
lib: Add ASan support to romstage on x86 arch
This patch adds ASan support to romstage on x86 architecture.
A Kconfig option is added to enable ASan in romstage. Compiler
flags are updated. A memory space representing the shadow region
is reserved in linker section. And a function call to asan_init()
is added to initialize shadow region when romstage loads.
Change-Id: I67ebfb5e8d602e865b1f5c874860861ae4e54381
Signed-off-by: Harshit Sharma <harshitsharmajs@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/43604
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
-rw-r--r-- | src/Kconfig | 7 | ||||
-rw-r--r-- | src/arch/x86/assembly_entry.S | 4 | ||||
-rw-r--r-- | src/arch/x86/car.ld | 6 | ||||
-rw-r--r-- | src/include/symbols.h | 7 | ||||
-rw-r--r-- | src/lib/Makefile.inc | 18 | ||||
-rw-r--r-- | src/lib/asan.c | 32 |
6 files changed, 65 insertions, 9 deletions
diff --git a/src/Kconfig b/src/Kconfig index f8af522823..447755be80 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -288,6 +288,13 @@ if ASAN_IN_RAMSTAGE comment "asan_shadow_offset_callback patch is applied to GCC." endif +config ASAN_IN_ROMSTAGE + bool + depends on ASAN_IN_RAMSTAGE + default n + help + Enable address sanitizer in romstage for platform. + choice prompt "Stage Cache for ACPI S3 resume" default NO_STAGE_CACHE if !HAVE_ACPI_RESUME diff --git a/src/arch/x86/assembly_entry.S b/src/arch/x86/assembly_entry.S index fb48469c55..0d8307bb1f 100644 --- a/src/arch/x86/assembly_entry.S +++ b/src/arch/x86/assembly_entry.S @@ -49,6 +49,10 @@ debug_spinloop: #if CONFIG(IDT_IN_EVERY_STAGE) call exception_init #endif + +#if CONFIG(ASAN_IN_ROMSTAGE) + call asan_init +#endif call car_stage_entry /* Expect to never return. */ diff --git a/src/arch/x86/car.ld b/src/arch/x86/car.ld index 17b774845b..eabe87380a 100644 --- a/src/arch/x86/car.ld +++ b/src/arch/x86/car.ld @@ -72,8 +72,12 @@ *(.sbss.*) . = ALIGN(ARCH_POINTER_ALIGN_SIZE); _ebss = .; - _car_unallocated_start = .; +#if ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE) + _shadow_size = (_ebss - _car_region_start) >> 3; + REGION(asan_shadow, ., _shadow_size, ARCH_POINTER_ALIGN_SIZE) +#endif + _car_unallocated_start = .; _car_region_end = . + CONFIG_DCACHE_RAM_SIZE - (. - _car_region_start); } . = _car_region_end; diff --git a/src/include/symbols.h b/src/include/symbols.h index 2fbb449122..57c52eed53 100644 --- a/src/include/symbols.h +++ b/src/include/symbols.h @@ -24,7 +24,12 @@ DECLARE_REGION(cbfs_cache) DECLARE_REGION(fmap_cache) DECLARE_REGION(tpm_tcpa_log) -#if CONFIG(ASAN_IN_RAMSTAGE) +#if ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE) +DECLARE_REGION(bss) +DECLARE_REGION(asan_shadow) +#endif + +#if ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE) DECLARE_REGION(data) DECLARE_REGION(heap) DECLARE_REGION(asan_shadow) diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index e33a44998c..4ce133a336 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -7,16 +7,24 @@ ramstage-y += ubsan.c CFLAGS_ramstage += -fsanitize=undefined endif -ifeq ($(CONFIG_ASAN_IN_RAMSTAGE),y) -ramstage-y += asan.c # Ensure that asan_shadow_offset_callback patch is applied to GCC before ASan is used. CFLAGS_asan += -fsanitize=kernel-address --param asan-use-shadow-offset-callback=1 \ - --param asan-stack=1 --param asan-globals=1 \ + --param asan-stack=1 -fsanitize-address-use-after-scope \ --param asan-instrumentation-with-call-threshold=0 \ - -fsanitize-address-use-after-scope \ --param use-after-scope-direct-emission-threshold=0 -CFLAGS_ramstage += $(CFLAGS_asan) + +ifeq ($(CONFIG_ASAN_IN_ROMSTAGE),y) +romstage-y += asan.c +CFLAGS_asan += --param asan-globals=0 +CFLAGS_romstage += $(CFLAGS_asan) # Allow memory access without __asan_load and __asan_store checks. +$(obj)/romstage/lib/asan.o: CFLAGS_asan = +endif + +ifeq ($(CONFIG_ASAN_IN_RAMSTAGE),y) +ramstage-y += asan.c +CFLAGS_asan += --param asan-globals=1 +CFLAGS_ramstage += $(CFLAGS_asan) $(obj)/ramstage/lib/asan.o: CFLAGS_asan = endif diff --git a/src/lib/asan.c b/src/lib/asan.c index 0c186d62a3..11dbf7c657 100644 --- a/src/lib/asan.c +++ b/src/lib/asan.c @@ -10,18 +10,29 @@ #include <symbols.h> #include <assert.h> +#include <arch/symbols.h> #include <asan.h> static inline void *asan_mem_to_shadow(const void *addr) { +#if ENV_ROMSTAGE + return (void *)((uintptr_t)&_asan_shadow + (((uintptr_t)addr - + (uintptr_t)&_car_region_start) >> ASAN_SHADOW_SCALE_SHIFT)); +#elif ENV_RAMSTAGE return (void *)((uintptr_t)&_asan_shadow + (((uintptr_t)addr - (uintptr_t)&_data) >> ASAN_SHADOW_SCALE_SHIFT)); +#endif } static inline const void *asan_shadow_to_mem(const void *shadow_addr) { +#if ENV_ROMSTAGE + return (void *)((uintptr_t)&_car_region_start + (((uintptr_t)shadow_addr - + (uintptr_t)&_asan_shadow) << ASAN_SHADOW_SCALE_SHIFT)); +#elif ENV_RAMSTAGE return (void *)((uintptr_t)&_data + (((uintptr_t)shadow_addr - (uintptr_t)&_asan_shadow) << ASAN_SHADOW_SCALE_SHIFT)); +#endif } static void asan_poison_shadow(const void *address, size_t size, u8 value) @@ -225,10 +236,15 @@ static __always_inline void check_memory_region_inline(unsigned long addr, size_t size, bool write, unsigned long ret_ip) { +#if ENV_ROMSTAGE + if (((uintptr_t)addr < (uintptr_t)&_car_region_start) || + ((uintptr_t)addr > (uintptr_t)&_ebss)) + return; +#elif ENV_RAMSTAGE if (((uintptr_t)addr < (uintptr_t)&_data) || - ((uintptr_t)addr > (uintptr_t)&_eheap)) + ((uintptr_t)addr > (uintptr_t)&_eheap)) return; - +#endif if (unlikely(size == 0)) return; @@ -252,8 +268,13 @@ static void check_memory_region(unsigned long addr, size_t size, bool write, uintptr_t __asan_shadow_offset(uintptr_t addr) { +#if ENV_ROMSTAGE + return (uintptr_t)&_asan_shadow - (((uintptr_t)&_car_region_start) >> + ASAN_SHADOW_SCALE_SHIFT); +#elif ENV_RAMSTAGE return (uintptr_t)&_asan_shadow - (((uintptr_t)&_data) >> ASAN_SHADOW_SCALE_SHIFT); +#endif } static void register_global(struct asan_global *global) @@ -285,6 +306,7 @@ void __asan_unregister_globals(struct asan_global *globals, size_t size) * to it so we could poison variable's redzone. * This function calls those constructors. */ +#if ENV_RAMSTAGE static void asan_ctors(void) { extern long __CTOR_LIST__; @@ -296,12 +318,18 @@ static void asan_ctors(void) for (; *ctor != (func_ptr) 0; ctor++) (*ctor)(); } +#endif void asan_init(void) { +#if ENV_ROMSTAGE + size_t size = (size_t)&_ebss - (size_t)&_car_region_start; + asan_unpoison_shadow((void *)&_car_region_start, size); +#elif ENV_RAMSTAGE size_t size = (size_t)&_eheap - (size_t)&_data; asan_unpoison_shadow((void *)&_data, size); asan_ctors(); +#endif } void __asan_poison_stack_memory(const void *addr, size_t size) |