cmake: Enable undefined behavior sanitizer on all targets

GCC and Clang support the undefined behavior sanitizer in any
configuration, the only restriction is that if you want to get nice
messages printed, then you need the ubsan library routines which are only
present for posix architecture or when using picolibc.

This patch adds three new compiler properties:

 * sanitizer_undefined. Enables the undefined behavior sanitizer.
 * sanitizer_undefined_library. Calls ubsan library routines on fault.
 * sanitizer_undefined_trap. Invokes __builtin_trap() on fault.

Overhead for using the trapping sanitizer is fairly low and should be
considered for use in CI once all of the undefined behavior faults in
Zephyr are fixed.

Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Keith Packard 2025-04-07 15:23:02 -07:00 committed by Benjamin Cabé
commit 2d64237f44
6 changed files with 50 additions and 5 deletions

View file

@ -344,6 +344,18 @@ if (CONFIG_PICOLIBC AND NOT CONFIG_PICOLIBC_IO_FLOAT)
zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,no_printf_return_value>>)
endif()
if(CONFIG_UBSAN)
zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,sanitizer_undefined>>)
zephyr_link_libraries($<TARGET_PROPERTY:linker,sanitizer_undefined>)
if(CONFIG_UBSAN_LIBRARY)
zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,sanitizer_undefined_library>>)
zephyr_link_libraries($<TARGET_PROPERTY:linker,sanitizer_undefined_library>)
elseif(CONFIG_UBSAN_TRAP)
zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,sanitizer_undefined_trap>>)
zephyr_link_libraries($<TARGET_PROPERTY:linker,sanitizer_undefined_trap>)
endif()
endif()
# @Intent: Set compiler specific flag for tentative definitions, no-common
zephyr_compile_options($<TARGET_PROPERTY:compiler,no_common>)

View file

@ -327,6 +327,7 @@ config PRIVILEGED_STACK_SIZE
config KOBJECT_TEXT_AREA
int "Size of kobject text area"
default 1024 if UBSAN
default 512 if COVERAGE_GCOV
default 512 if NO_OPTIMIZATIONS
default 512 if STACK_CANARIES && RISCV

View file

@ -126,6 +126,7 @@ config PRIVILEGED_STACK_SIZE
default 4096
config KOBJECT_TEXT_AREA
default 1024 if UBSAN
default 512 if TEST
config WAIT_AT_RESET_VECTOR

View file

@ -197,6 +197,10 @@ if(NOT CONFIG_NO_OPTIMIZATIONS)
set_compiler_property(PROPERTY security_fortify_run_time _FORTIFY_SOURCE=2)
endif()
check_set_compiler_property(PROPERTY sanitizer_undefined -fsanitize=undefined)
check_set_compiler_property(PROPERTY sanitizer_undefined_trap -fsanitize-undefined-trap-on-error)
check_set_compiler_property(PROPERTY sanitizer_undefined_library)
# gcc flag for a hosted (no-freestanding) application
check_set_compiler_property(APPEND PROPERTY hosted -fno-freestanding)

View file

@ -24,6 +24,10 @@ check_set_linker_property(TARGET linker PROPERTY orphan_error
check_set_linker_property(TARGET linker PROPERTY memusage "${LINKERFLAGPREFIX},--print-memory-usage")
check_set_linker_property(TARGET linker PROPERTY sanitizer_undefined -fsanitize=undefined)
check_set_linker_property(TARGET linker PROPERTY sanitizer_undefined_trap -fsanitize-undefined-trap-on-error)
check_set_linker_property(TARGET linker PROPERTY sanitizer_undefined_library)
# -no-pie is not supported until binutils 2.37.
# If -no-pie is passed to old binutils <= 2.36, it is parsed
# as separate arguments -n and -o, which results in output file

View file

@ -67,12 +67,35 @@ config ASAN_NOP_DLCLOSE
config UBSAN
bool "Build with undefined behavior sanitizer"
depends on ARCH_POSIX
help
Builds Zephyr with Undefined Behavior Sanitizer enabled.
This is currently only supported by boards based on the posix
architecture, and requires a recent-ish compiler with the
``-fsanitize=undefined`` command line option.
Builds Zephyr with Undefined Behavior Sanitizer enabled. This
requires a recent-ish compiler with the ``-fsanitize=undefined``
command line option.
choice UBSAN_MODE
prompt "Undefined behavior sanitizer mode"
depends on UBSAN
default UBSAN_LIBRARY
config UBSAN_LIBRARY
bool "Call ubsan routines"
depends on ARCH_POSIX || PICOLIBC
help
Call ubsan library routines when undefined behavior is detected
at runtime. This provides information about the faulting
condition along with the source filename, line number, types and
values involved. This is currently only supported by boards
based on the posix architecture or when building with picolibc.
config UBSAN_TRAP
bool "Call __builtin_trap"
help
When undefined behavior is detected, invoke __builtin_trap to
cause an exception to be raised. This can be used on any target,
but the lack of information makes figuring out the triggering
code difficult.
endchoice
config MSAN
bool "Build with memory sanitizer"