summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHarshit Sharma <harshitsharmajs@gmail.com>2020-07-20 00:21:05 -0700
committerPatrick Georgi <pgeorgi@google.com>2020-08-21 07:41:19 +0000
commita6ebe08333dcc6c263b6bb8936d4883663c63798 (patch)
tree8f06ee5f79cf4efb54f189c17512a6120d2edd40 /src
parent9c88fb8df0005dc60e6c62778b4f16313cb3308e (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>
Diffstat (limited to 'src')
-rw-r--r--src/Kconfig7
-rw-r--r--src/arch/x86/assembly_entry.S4
-rw-r--r--src/arch/x86/car.ld6
-rw-r--r--src/include/symbols.h7
-rw-r--r--src/lib/Makefile.inc18
-rw-r--r--src/lib/asan.c32
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)