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.coul...@canonical.com> --- grub-core/Makefile.core.def | 4 +++- 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 ac00cc8a2..7e831d124 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 7facacf09..7cb3f77e0 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -31,6 +31,11 @@ #ifdef GRUB_STACK_PROTECTOR +static const 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 { -- 2.35.1 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel