security: Additional option for stack canaries

Previously, when stack canaries were enabled, Zephyr applied this
protection to all functions. This commit introduces a new option that
allows stack canary protection to be applied selectively to specific
functions based on certain criteria.

Signed-off-by: Flavio Ceolin <flavio.ceolin@gmail.com>
This commit is contained in:
Flavio Ceolin 2024-11-25 13:58:40 -08:00 committed by Benjamin Cabé
commit 82ace41da4
9 changed files with 47 additions and 18 deletions

View file

@ -175,6 +175,8 @@ endif()
# @Intent: Set compiler flags to detect general stack overflows across all functions # @Intent: Set compiler flags to detect general stack overflows across all functions
if(CONFIG_STACK_CANARIES) if(CONFIG_STACK_CANARIES)
zephyr_compile_options($<TARGET_PROPERTY:compiler,security_canaries>) zephyr_compile_options($<TARGET_PROPERTY:compiler,security_canaries>)
elseif(CONFIG_STACK_CANARIES_STRONG)
zephyr_compile_options($<TARGET_PROPERTY:compiler,security_canaries_strong>)
endif() endif()
# @Intent: Obtain compiler optimizations flags and store in variables # @Intent: Obtain compiler optimizations flags and store in variables

View file

@ -168,6 +168,7 @@ set_compiler_property(PROPERTY imacros -imacros)
# Security canaries. # Security canaries.
#no support of -mstack-protector-guard=global" #no support of -mstack-protector-guard=global"
set_compiler_property(PROPERTY security_canaries -fstack-protector-all) set_compiler_property(PROPERTY security_canaries -fstack-protector-all)
set_compiler_property(PROPERTY security_canaries_strong -fstack-protector-strong)
#no support of _FORTIFY_SOURCE" #no support of _FORTIFY_SOURCE"
set_compiler_property(PROPERTY security_fortify_compile_time) set_compiler_property(PROPERTY security_fortify_compile_time)

View file

@ -92,6 +92,7 @@ set_compiler_property(PROPERTY coverage)
# Security canaries flags. # Security canaries flags.
set_compiler_property(PROPERTY security_canaries) set_compiler_property(PROPERTY security_canaries)
set_compiler_property(PROPERTY security_canaries_strong)
set_compiler_property(PROPERTY security_fortify_compile_time) set_compiler_property(PROPERTY security_fortify_compile_time)
set_compiler_property(PROPERTY security_fortify_run_time) set_compiler_property(PROPERTY security_fortify_run_time)

View file

@ -168,12 +168,15 @@ set_compiler_property(PROPERTY coverage -fprofile-arcs -ftest-coverage -fno-inli
# Security canaries. # Security canaries.
set_compiler_property(PROPERTY security_canaries -fstack-protector-all) set_compiler_property(PROPERTY security_canaries -fstack-protector-all)
set_compiler_property(PROPERTY security_canaries_strong -fstack-protector-strong)
# Only a valid option with GCC 7.x and above, so let's do check and set. # Only a valid option with GCC 7.x and above, so let's do check and set.
if(CONFIG_STACK_CANARIES_TLS) if(CONFIG_STACK_CANARIES_TLS)
check_set_compiler_property(APPEND PROPERTY security_canaries -mstack-protector-guard=tls) check_set_compiler_property(APPEND PROPERTY security_canaries -mstack-protector-guard=tls)
check_set_compiler_property(APPEND PROPERTY security_canaries_strong -mstack-protector-guard=tls)
else() else()
check_set_compiler_property(APPEND PROPERTY security_canaries -mstack-protector-guard=global) check_set_compiler_property(APPEND PROPERTY security_canaries -mstack-protector-guard=global)
check_set_compiler_property(APPEND PROPERTY security_canaries_global -mstack-protector-guard=global)
endif() endif()

View file

@ -140,7 +140,7 @@ set_target_properties(
__ZEPHYR_SUPERVISOR__ __ZEPHYR_SUPERVISOR__
) )
target_sources_ifdef(CONFIG_STACK_CANARIES kernel PRIVATE compiler_stack_protect.c) target_sources_ifdef(CONFIG_REQUIRES_STACK_CANARIES kernel PRIVATE compiler_stack_protect.c)
target_sources_ifdef(CONFIG_SYS_CLOCK_EXISTS kernel PRIVATE timeout.c timer.c) target_sources_ifdef(CONFIG_SYS_CLOCK_EXISTS kernel PRIVATE timeout.c timer.c)
target_sources_ifdef(CONFIG_ATOMIC_OPERATIONS_C kernel PRIVATE atomic_c.c) target_sources_ifdef(CONFIG_ATOMIC_OPERATIONS_C kernel PRIVATE atomic_c.c)
target_sources_ifdef(CONFIG_MMU kernel PRIVATE mmu.c) target_sources_ifdef(CONFIG_MMU kernel PRIVATE mmu.c)

View file

@ -869,25 +869,47 @@ config XIP
menu "Security Options" menu "Security Options"
config STACK_CANARIES config REQUIRES_STACK_CANARIES
bool "Compiler stack canaries" bool
depends on ENTROPY_GENERATOR || TEST_RANDOM_GENERATOR
select NEED_LIBC_MEM_PARTITION if !STACK_CANARIES_TLS
help help
This option enables compiler stack canaries. Hidden option to signal that software stack protection is required.
choice
prompt "Stack canaries protection options"
optional
help
If stack canaries are supported by the compiler, it will emit If stack canaries are supported by the compiler, it will emit
extra code that inserts a canary value into the stack frame when extra code that inserts a canary value into the stack frame when
a function is entered and validates this value upon exit. a function is entered and validates this value upon exit.
Stack corruption (such as that caused by buffer overflow) results Stack corruption (such as that caused by buffer overflow) results
in a fatal error condition for the running entity. in a fatal error condition for the running entity.
Enabling this option can result in a significant increase Enabling this option, depending on the level chosen, can result in a
in footprint and an associated decrease in performance. significant increase in footprint and a corresponding decrease in performance.
If stack canaries are not supported by the compiler an error If stack canaries are not supported by the compiler an error
will occur at build time. will occur at build time.
if STACK_CANARIES config STACK_CANARIES
bool "Maximum protection available"
depends on ENTROPY_GENERATOR || TEST_RANDOM_GENERATOR
select NEED_LIBC_MEM_PARTITION if !STACK_CANARIES_TLS
select REQUIRES_STACK_CANARIES
help
This option enables compiler stack canaries for all functions.
config STACK_CANARIES_STRONG
bool "Strong protection"
depends on ENTROPY_GENERATOR || TEST_RANDOM_GENERATOR
select NEED_LIBC_MEM_PARTITION if !STACK_CANARIES_TLS
select REQUIRES_STACK_CANARIES
help
This option enables compiler stack canaries in functions that call alloca,
functions that have local array definitiion or have references to local
frame addresses.
endchoice
if REQUIRES_STACK_CANARIES
config STACK_CANARIES_TLS config STACK_CANARIES_TLS
bool "Stack canaries using thread local storage" bool "Stack canaries using thread local storage"

View file

@ -10,7 +10,7 @@
* *
* This module provides functions to support compiler stack protection * This module provides functions to support compiler stack protection
* using canaries. This feature is enabled with configuration * using canaries. This feature is enabled with configuration
* CONFIG_STACK_CANARIES=y. * CONFIG_STACK_CANARIES=y or CONFIG_STACK_CANARIES_STRONG=y.
* *
* When this feature is enabled, the compiler generated code refers to * When this feature is enabled, the compiler generated code refers to
* function __stack_chk_fail and global variable __stack_chk_guard. * function __stack_chk_fail and global variable __stack_chk_guard.

View file

@ -289,13 +289,13 @@ void z_bss_zero_pinned(void)
} }
#endif /* CONFIG_LINKER_USE_PINNED_SECTION */ #endif /* CONFIG_LINKER_USE_PINNED_SECTION */
#ifdef CONFIG_STACK_CANARIES #ifdef CONFIG_REQUIRES_STACK_CANARIES
#ifdef CONFIG_STACK_CANARIES_TLS #ifdef CONFIG_STACK_CANARIES_TLS
extern Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard; extern Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard;
#else #else
extern volatile uintptr_t __stack_chk_guard; extern volatile uintptr_t __stack_chk_guard;
#endif /* CONFIG_STACK_CANARIES_TLS */ #endif /* CONFIG_STACK_CANARIES_TLS */
#endif /* CONFIG_STACK_CANARIES */ #endif /* CONFIG_REQUIRES_STACK_CANARIES */
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
@ -778,13 +778,13 @@ FUNC_NORETURN void z_cstart(void)
#endif #endif
z_sys_init_run_level(INIT_LEVEL_PRE_KERNEL_2); z_sys_init_run_level(INIT_LEVEL_PRE_KERNEL_2);
#ifdef CONFIG_STACK_CANARIES #ifdef CONFIG_REQUIRES_STACK_CANARIES
uintptr_t stack_guard; uintptr_t stack_guard;
z_early_rand_get((uint8_t *)&stack_guard, sizeof(stack_guard)); z_early_rand_get((uint8_t *)&stack_guard, sizeof(stack_guard));
__stack_chk_guard = stack_guard; __stack_chk_guard = stack_guard;
__stack_chk_guard <<= 8; __stack_chk_guard <<= 8;
#endif /* CONFIG_STACK_CANARIES */ #endif /* CONFIG_REQUIRES_STACK_CANARIES */
#ifdef CONFIG_TIMING_FUNCTIONS_NEED_AT_BOOT #ifdef CONFIG_TIMING_FUNCTIONS_NEED_AT_BOOT
timing_init(); timing_init();

View file

@ -10,13 +10,13 @@
#include <kernel_internal.h> #include <kernel_internal.h>
#include <zephyr/linker/linker-defs.h> #include <zephyr/linker/linker-defs.h>
#ifdef CONFIG_STACK_CANARIES #ifdef CONFIG_REQUIRES_STACK_CANARIES
#ifdef CONFIG_STACK_CANARIES_TLS #ifdef CONFIG_STACK_CANARIES_TLS
extern Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard; extern Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard;
#else #else
extern volatile uintptr_t __stack_chk_guard; extern volatile uintptr_t __stack_chk_guard;
#endif /* CONFIG_STACK_CANARIES_TLS */ #endif /* CONFIG_STACK_CANARIES_TLS */
#endif /* CONFIG_STACK_CANARIES */ #endif /* CONFIG_REQUIRES_STACK_CANARIES */
/** /**
* @brief Copy the data section from ROM to RAM * @brief Copy the data section from ROM to RAM
@ -49,7 +49,7 @@ void z_data_copy(void)
data_copy_xip_relocation(); data_copy_xip_relocation();
#endif /* CONFIG_CODE_DATA_RELOCATION */ #endif /* CONFIG_CODE_DATA_RELOCATION */
#ifdef CONFIG_USERSPACE #ifdef CONFIG_USERSPACE
#ifdef CONFIG_STACK_CANARIES #ifdef CONFIG_REQUIRES_STACK_CANARIES
/* stack canary checking is active for all C functions. /* stack canary checking is active for all C functions.
* __stack_chk_guard is some uninitialized value living in the * __stack_chk_guard is some uninitialized value living in the
* app shared memory sections. Preserve it, and don't make any * app shared memory sections. Preserve it, and don't make any
@ -70,6 +70,6 @@ void z_data_copy(void)
#else #else
z_early_memcpy(&_app_smem_start, &_app_smem_rom_start, z_early_memcpy(&_app_smem_start, &_app_smem_rom_start,
_app_smem_end - _app_smem_start); _app_smem_end - _app_smem_start);
#endif /* CONFIG_STACK_CANARIES */ #endif /* CONFIG_REQUIRES_STACK_CANARIES */
#endif /* CONFIG_USERSPACE */ #endif /* CONFIG_USERSPACE */
} }