diff --git a/meson.build b/meson.build index b1521e5937..b575b04dc6 100644 --- a/meson.build +++ b/meson.build @@ -397,7 +397,14 @@ possible_common_cc_flags = [ '-Wno-error=#warnings', # clang '-Wno-string-plus-int', # clang + '-fstack-protector', + '-fstack-protector-strong', '-fstrict-flex-arrays', + '--param=ssp-buffer-size=4', +] + +possible_common_link_flags = [ + '-fstack-protector', ] c_args = get_option('c_args') @@ -432,7 +439,6 @@ possible_link_flags = [ '-Wl,--fatal-warnings', '-Wl,-z,now', '-Wl,-z,relro', - '-fstack-protector', ] if get_option('b_sanitize') == 'none' @@ -459,11 +465,8 @@ possible_cc_flags = [ '-fdiagnostics-show-option', '-fno-common', '-fno-strict-aliasing', - '-fstack-protector', - '-fstack-protector-strong', '-fstrict-flex-arrays=1', '-fvisibility=hidden', - '--param=ssp-buffer-size=4', ] if get_option('buildtype') != 'debug' @@ -486,6 +489,10 @@ add_project_arguments( ), language : 'c') +add_project_link_arguments( + cc.get_supported_link_arguments(possible_common_link_flags), + language : 'c') + userspace_c_args += cc.get_supported_arguments(possible_cc_flags) userspace_c_ld_args += cc.get_supported_link_arguments(possible_link_flags) diff --git a/src/boot/efi/log.c b/src/boot/efi/log.c index b805f5d084..6ba8d2d58e 100644 --- a/src/boot/efi/log.c +++ b/src/boot/efi/log.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "log.h" +#include "proto/rng.h" #include "proto/simple-text-io.h" static unsigned log_count = 0; @@ -59,6 +60,27 @@ void log_wait(void) { log_count = 0; } +_used_ intptr_t __stack_chk_guard = (intptr_t) 0x70f6967de78acae3; + +/* We can only set a random stack canary if this function attribute is available, + * otherwise this may create a stack check fail. */ +#if STACK_PROTECTOR_RANDOM +void __stack_chk_guard_init(void) { + EFI_RNG_PROTOCOL *rng; + if (BS->LocateProtocol(MAKE_GUID_PTR(EFI_RNG_PROTOCOL), NULL, (void **) &rng) == EFI_SUCCESS) + (void) rng->GetRNG(rng, NULL, sizeof(__stack_chk_guard), (void *) &__stack_chk_guard); +} +#endif + +_used_ _noreturn_ void __stack_chk_fail(void); +_used_ _noreturn_ void __stack_chk_fail_local(void); +void __stack_chk_fail(void) { + panic(u"systemd-boot: Stack check failed, halting."); +} +void __stack_chk_fail_local(void) { + __stack_chk_fail(); +} + #if defined(__ARM_EABI__) /* These override the (weak) div0 handlers from libgcc as they would otherwise call raise() instead. */ diff --git a/src/boot/efi/log.h b/src/boot/efi/log.h index 9bdcfad923..7b2735d028 100644 --- a/src/boot/efi/log.h +++ b/src/boot/efi/log.h @@ -3,6 +3,22 @@ #include "efi-string.h" +#if defined __has_attribute +# if __has_attribute(no_stack_protector) +# define HAVE_NO_STACK_PROTECTOR_ATTRIBUTE +# endif +#endif + +#if defined(HAVE_NO_STACK_PROTECTOR_ATTRIBUTE) && \ + (defined(__SSP__) || defined(__SSP_ALL__) || \ + defined(__SSP_STRONG__) || defined(__SSP_EXPLICIT__)) +# define STACK_PROTECTOR_RANDOM 1 +__attribute__((no_stack_protector, noinline)) void __stack_chk_guard_init(void); +#else +# define STACK_PROTECTOR_RANDOM 0 +# define __stack_chk_guard_init() +#endif + void log_wait(void); _gnu_printf_(2, 3) EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...); #define log_error_status(status, ...) log_internal(status, __VA_ARGS__) diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 7e497f7866..bfc3f9c279 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -139,6 +139,7 @@ efi_c_args += cc.get_supported_arguments( '-fwide-exec-charset=UCS2', # gcc docs says this is required for ms_abi to work correctly. '-maccumulate-outgoing-args', + '-mstack-protector-guard=global', ) # Debug information has little value in release builds as no normal human being knows @@ -180,8 +181,6 @@ efi_disabled_c_args = cc.get_supported_arguments( '-fno-exceptions', '-fno-trapv', '-fno-sanitize=all', - '-fno-stack-clash-protection', - '-fno-stack-protector', '-fno-unwind-tables', ) efi_c_args += efi_disabled_c_args diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h index 5e1085c788..5b4f47a1ae 100644 --- a/src/boot/efi/util.h +++ b/src/boot/efi/util.h @@ -176,6 +176,7 @@ void hexdump(const char16_t *prefix, const void *data, size_t size); ST = system_table; \ BS = system_table->BootServices; \ RT = system_table->RuntimeServices; \ + __stack_chk_guard_init(); \ notify_debugger((identity), (wait_for_debugger)); \ EFI_STATUS err = func(image); \ log_wait(); \