diff options
author | Chris Coulson <chris.coulson@canonical.com> | 2022-03-21 15:14:39 +0000 |
---|---|---|
committer | Daniel Kiper <daniel.kiper@oracle.com> | 2022-04-04 22:26:31 +0200 |
commit | 37ddd9457f13f92fd176bbb2951cfc1fbc93e6f7 (patch) | |
tree | 5d882312b8af73d7ffe60207cb7357ce7cf9d90b | |
parent | a97d1ebb8eda29f5676d6b347b3698598e8519eb (diff) | |
download | grub-37ddd9457f13f92fd176bbb2951cfc1fbc93e6f7.tar.gz |
kern/efi/init: Log a console error during a stack check failure
The initial implementation of the stack protector just busy looped
in __stack_chk_fail in order to reduce the amount of code being
executed after the stack has been compromised because of a lack of
firmware memory protections. With future firmware implementations
incorporating memory protections such as W^X, call in to boot services
when an error occurs in order to log a message to the console before
automatically rebooting the machine.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
-rw-r--r-- | grub-core/Makefile.core.def | 4 | ||||
-rw-r--r-- | grub-core/kern/efi/init.c | 23 |
2 files changed, 24 insertions, 3 deletions
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index cada67b66..715994872 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -50,12 +50,14 @@ kernel = { nostrip = emu; emu_ldflags = '-Wl,-r'; + i386_efi_cflags = '-fshort-wchar'; i386_efi_ldflags = '-Wl,-r'; i386_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + x86_64_efi_cflags = '-fshort-wchar'; x86_64_efi_ldflags = '-Wl,-r'; x86_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; - ia64_efi_cflags = '-fno-builtin -fpic -minline-int-divide-max-throughput'; + ia64_efi_cflags = '-fshort-wchar -fno-builtin -fpic -minline-int-divide-max-throughput'; ia64_efi_ldflags = '-Wl,-r'; ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 26ed07bb8..b67bc73a1 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -31,6 +31,11 @@ #ifdef GRUB_STACK_PROTECTOR +static grub_efi_char16_t stack_chk_fail_msg[] = + L"* GRUB: STACK SMASHING DETECTED!!! *\r\n" + L"* GRUB: ABORTED!!! *\r\n" + L"* GRUB: REBOOTING IN 5 SECONDS... *\r\n"; + static grub_efi_guid_t rng_protocol_guid = GRUB_EFI_RNG_PROTOCOL_GUID; /* @@ -44,9 +49,23 @@ grub_addr_t __stack_chk_guard; void __attribute__ ((noreturn)) __stack_chk_fail (void) { + grub_efi_simple_text_output_interface_t *o; + + /* + * Use ConOut here rather than StdErr. StdErr only goes to + * the serial console, at least on EDK2. + */ + o = grub_efi_system_table->con_out; + efi_call_2 (o->output_string, o, stack_chk_fail_msg); + + efi_call_1 (grub_efi_system_table->boot_services->stall, 5000000); + efi_call_4 (grub_efi_system_table->runtime_services->reset_system, + GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_ABORTED, 0, NULL); + /* - * Assume it's not safe to call into EFI Boot Services. Sorry, that - * means no console message here. + * We shouldn't get here. It's unsafe to return because the stack + * is compromised and this function is noreturn, so just busy + * loop forever. */ do { |