Skip to content

Commit

Permalink
cmake: Update CONFIG_ASAN support
Browse files Browse the repository at this point in the history
This had bitrotten a bit, and didn't build as shipped.  Current
libasan implementations want -fsanitize=address passed as a linker
argument too.  We have grown a "lld" linker variant that needs the
same cmake treatment as the "ld" binutils one, but never got it.  But
the various flags had been cut/pasted around to different places, with
slightly different forms.  That's really sort of a mess, as sanitizer
support was only ever support with host toolchains for native_posix
(and AFAICT no one anywhere has made this work on cross compilers in
an embedded environment).  And the separate "gcc" vs. "llvm" layers
were silly, as there has only ever been one API for this feature (from
LLVM, then picked up compatibly by gcc).

Pull this stuff out and just do it in one place in the posix arch for
simplicity.

Also recent sanitizers are trying to add instrumentation padding
around data that we use linker trickery to pack tightly
(c.f. SYS_INIT, STRUCT_SECTION_ITERABLE) and we need a way
("__noasan") to turn that off.  Actually for gcc, it was enough to
just make the records const (already true for most of them, except a
native_posix init struct), but clang apparently isn't smart enough.

Finally, add an ASAN_RECOVER kconfig that enables the use of
"halt_on_error=0" in $ASAN_OPTIONS, which continues execution past the
first error.

Signed-off-by: Andy Ross <[email protected]>
  • Loading branch information
andyross authored and aescolar committed Aug 19, 2022
1 parent d629798 commit 74cc534
Show file tree
Hide file tree
Showing 13 changed files with 61 additions and 43 deletions.
33 changes: 24 additions & 9 deletions arch/posix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,6 @@ if (CONFIG_GPROF)
zephyr_compile_options($<TARGET_PROPERTY:compiler,gprof>)
zephyr_link_libraries($<TARGET_PROPERTY:linker,gprof>)
endif()
if (CONFIG_ASAN)
zephyr_compile_options($<TARGET_PROPERTY:compiler,sanitize_address>)
zephyr_link_libraries($<TARGET_PROPERTY:linker,sanitize_address>)
endif ()

if (CONFIG_UBSAN)
zephyr_compile_options($<TARGET_PROPERTY:compiler,sanitize_undefined>)
zephyr_link_libraries($<TARGET_PROPERTY:linker,sanitize_undefined>)
endif ()

zephyr_compile_definitions(_POSIX_C_SOURCE=200809 _XOPEN_SOURCE=600 _XOPEN_SOURCE_EXTENDED)

Expand All @@ -53,5 +44,29 @@ zephyr_ld_options(
# Zephyr which will clash with the native POSIX API] . It would also need to
# be included in a few zephyr kernel files.

#
# Support for the LLVM Sanitizer toolchain instrumentation frameworks
# (supported by current gcc's as well)
#

if(CONFIG_ASAN)
list(APPEND LLVM_SANITIZERS "address")
endif()

if(CONFIG_UBSAN)
list(APPEND LLVM_SANITIZERS "undefined")
endif()

if(CONFIG_ASAN_RECOVER)
zephyr_compile_options(-fsanitize-recover=all)
endif()

list(JOIN LLVM_SANITIZERS "," LLVM_SANITIZERS_ARG)
if(NOT ${LLVM_SANITIZERS_ARG} STREQUAL "")
set(LLVM_SANITIZERS_ARG "-fsanitize=${LLVM_SANITIZERS_ARG}")
zephyr_compile_options("${LLVM_SANITIZERS_ARG}")
zephyr_link_libraries("${LLVM_SANITIZERS_ARG}")
endif()


add_subdirectory(core)
5 changes: 0 additions & 5 deletions cmake/compiler/arcmwdt/compiler_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,6 @@ set_compiler_property(PROPERTY coverage "")
# mwdt compiler flags for imacros. The specific header must be appended by user.
set_compiler_property(PROPERTY imacros -imacros)

#no support of -fsanitize=address and -lasan
set_compiler_property(PROPERTY sanitize_address "")

set_compiler_property(PROPERTY sanitize_undefined "")

# Security canaries.
#no support of -mstack-protector-guard=global"
set_compiler_property(PROPERTY security_canaries -fstack-protector-all)
Expand Down
5 changes: 0 additions & 5 deletions cmake/compiler/compiler_flags_template.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ set_compiler_property(PROPERTY no_common)
# Flags for imacros. The specific header must be appended by user.
set_compiler_property(PROPERTY imacros)

# Compiler flags for sanitizing.
set_compiler_property(PROPERTY sanitize_address)

set_compiler_property(PROPERTY sanitize_undefined)

# Compiler flag for turning off thread-safe initialization of local statics
set_property(TARGET compiler-cpp PROPERTY no_threadsafe_statics)

Expand Down
5 changes: 0 additions & 5 deletions cmake/compiler/gcc/compiler_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,8 @@ set_compiler_property(PROPERTY no_common -fno-common)
# GCC compiler flags for imacros. The specific header must be appended by user.
set_compiler_property(PROPERTY imacros -imacros)

# GCC compiler flags for sanitizing.
set_compiler_property(PROPERTY sanitize_address -fsanitize=address)

set_compiler_property(PROPERTY gprof -pg)

set_compiler_property(PROPERTY sanitize_undefined -fsanitize=undefined)

# GCC compiler flag for turning off thread-safe initialization of local statics
set_property(TARGET compiler-cpp PROPERTY no_threadsafe_statics "-fno-threadsafe-statics")

Expand Down
5 changes: 0 additions & 5 deletions cmake/linker/ld/clang/linker_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,3 @@
if (NOT CONFIG_COVERAGE_GCOV)
set_property(TARGET linker PROPERTY coverage --coverage)
endif()

# ld/clang linker flags for sanitizing.
check_set_linker_property(TARGET linker APPEND PROPERTY sanitize_address -fsanitize=address)

check_set_linker_property(TARGET linker APPEND PROPERTY sanitize_undefined -fsanitize=undefined)
5 changes: 0 additions & 5 deletions cmake/linker/ld/gcc/linker_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@ if (NOT CONFIG_COVERAGE_GCOV)
set_property(TARGET linker PROPERTY coverage -lgcov)
endif()

# ld/gcc linker flags for sanitizing.
check_set_linker_property(TARGET linker APPEND PROPERTY sanitize_address -lasan)
check_set_linker_property(TARGET linker APPEND PROPERTY sanitize_address -fsanitize=address)
check_set_linker_property(TARGET linker APPEND PROPERTY sanitize_undefined -fsanitize=undefined)

check_set_linker_property(TARGET linker APPEND PROPERTY gprof -pg)
5 changes: 0 additions & 5 deletions cmake/linker/linker_flags_template.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
# Set the property for the corresponding flags of the given toolchain.
set_property(TARGET linker PROPERTY coverage)

# Linker flags for sanitizing.
check_set_linker_property(TARGET linker APPEND PROPERTY sanitize_address)

check_set_linker_property(TARGET linker APPEND PROPERTY sanitize_undefined)

# Linker flag for printing of memusage.
# Set this flag if the linker supports reporting of memusage as part of link,
# such as ls --print-memory-usage flag.
Expand Down
2 changes: 1 addition & 1 deletion include/zephyr/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void z_sys_init_run_level(int32_t level);
*/
#define Z_INIT_ENTRY_DEFINE(_entry_name, _init_fn, _device, _level, _prio) \
static const Z_DECL_ALIGN(struct init_entry) \
Z_INIT_ENTRY_NAME(_entry_name) __used \
Z_INIT_ENTRY_NAME(_entry_name) __used __noasan \
__attribute__((__section__(".z_init_" #_level STRINGIFY(_prio)"_"))) = { \
.init = (_init_fn), \
.dev = (_device), \
Expand Down
15 changes: 15 additions & 0 deletions include/zephyr/toolchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@
#error "Invalid/unknown toolchain configuration"
#endif

/**
* @def __noasan
* @brief Disable address sanitizer
*
* When used in the definiton of a symbol, prevents that symbol (be it
* a function or data) from being instrumented by the address
* sanitizer feature of the compiler. Most commonly, this is used to
* prevent padding around data that will be treated specially by the
* Zephyr link (c.f. SYS_INIT records, STRUCT_SECTION_ITERABLE
* definitions) in ways that don't understand the guard padding.
*/
#ifndef __noasan
#define __noasan /**/
#endif

/**
* @def GCC_VERSION
* @brief GCC version in xxyyzz for xx.yy.zz. Zero if not GCC compatible.
Expand Down
4 changes: 2 additions & 2 deletions include/zephyr/toolchain/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@
*/
#define STRUCT_SECTION_ITERABLE(struct_type, name) \
Z_DECL_ALIGN(struct struct_type) name \
__in_section(_##struct_type, static, name) __used
__in_section(_##struct_type, static, name) __used __noasan

/**
* @brief Defines an alternate data type iterable section.
Expand All @@ -221,7 +221,7 @@
*/
#define STRUCT_SECTION_ITERABLE_ALTERNATE(out_type, struct_type, name) \
Z_DECL_ALIGN(struct struct_type) name \
__in_section(_##out_type, static, name) __used
__in_section(_##out_type, static, name) __used __noasan

/**
* @brief Iterate over a specified iterable section.
Expand Down
6 changes: 6 additions & 0 deletions include/zephyr/toolchain/gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -618,5 +618,11 @@ do { \
*/
#define Z_IS_POW2(x) (((x) != 0) && (((x) & ((x)-1)) == 0))

#ifdef CONFIG_ASAN
#define __noasan __attribute__((no_sanitize("address")))
#else
#define __noasan /**/
#endif

#endif /* !_LINKER */
#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_GCC_H_ */
2 changes: 1 addition & 1 deletion soc/posix/inf_clock/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void posix_soc_clean_up(void);
* any Zephyr thread are running.
*/
#define NATIVE_TASK(fn, level, prio) \
static void (*_CONCAT(__native_task_, fn)) __used \
static const void (*_CONCAT(__native_task_, fn)) __used __noasan \
__attribute__((__section__(".native_" #level STRINGIFY(prio) "_task")))\
= fn

Expand Down
12 changes: 12 additions & 0 deletions subsys/debug/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ config ASAN
This behavior can be changes by adding leak_check_at_exit=1 to the
environment variable ASAN_OPTIONS.

config ASAN_RECOVER
bool "Continue after sanitizer errors"
depends on ASAN
default y
help
The default behavior of compiler sanitizers is to exit after
the first error. Set this to y to enable the code to
continue, which can be useful if a code base has known
unsuppressed errors. You will also need to set
"halt_on_error=0" in your ASAN_OPTIONS environment variable
at runtime.

config ASAN_NOP_DLCLOSE
bool "Override host OS dlclose() with a NOP"
default y if HAS_SDL
Expand Down

0 comments on commit 74cc534

Please sign in to comment.