diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 6c54af6e7..1637077e1 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -39,12 +39,6 @@ static grub_efi_char16_t stack_chk_fail_msg[] = static grub_guid_t rng_protocol_guid = GRUB_EFI_RNG_PROTOCOL_GUID; -/* - * Don't put this on grub_efi_init()'s local stack to avoid it - * getting a stack check. - */ -static grub_efi_uint8_t stack_chk_guard_buf[32]; - /* Initialize canary in case there is no RNG protocol. */ grub_addr_t __stack_chk_guard = (grub_addr_t) GRUB_STACK_PROTECTOR_INIT; @@ -77,8 +71,8 @@ __stack_chk_fail (void) while (1); } -static void -stack_protector_init (void) +grub_addr_t +grub_stack_protector_init (void) { grub_efi_rng_protocol_t *rng; @@ -87,23 +81,20 @@ stack_protector_init (void) if (rng != NULL) { grub_efi_status_t status; + grub_addr_t guard = 0; - status = rng->get_rng (rng, NULL, sizeof (stack_chk_guard_buf), - stack_chk_guard_buf); + status = rng->get_rng (rng, NULL, sizeof (guard) - 1, + (grub_efi_uint8_t *) &guard); if (status == GRUB_EFI_SUCCESS) - grub_memcpy (&__stack_chk_guard, stack_chk_guard_buf, sizeof (__stack_chk_guard)); + return guard; } -} -#else -static void -stack_protector_init (void) -{ + return 0; } #endif grub_addr_t grub_modbase; -__attribute__ ((__optimize__ ("-fno-stack-protector"))) void +void grub_efi_init (void) { grub_modbase = grub_efi_section_addr ("mods"); @@ -111,8 +102,6 @@ grub_efi_init (void) messages. */ grub_console_init (); - stack_protector_init (); - /* Initialize the memory management system. */ grub_efi_mm_init (); diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index 731c07c29..744197785 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -265,6 +266,16 @@ reclaim_module_space (void) void __attribute__ ((noreturn)) grub_main (void) { +#ifdef GRUB_STACK_PROTECTOR + /* + * This call should only be made from a function that does not return because + * functions that return will get instrumented to check that the stack cookie + * does not change and this call will change the stack cookie. Thus a stack + * guard failure will be triggered. + */ + grub_update_stack_guard (); +#endif + /* First of all, initialize the machine. */ grub_machine_init (); diff --git a/include/grub/stack_protector.h b/include/grub/stack_protector.h index 13d2657d9..e4849b2a0 100644 --- a/include/grub/stack_protector.h +++ b/include/grub/stack_protector.h @@ -29,6 +29,18 @@ extern void __attribute__ ((noreturn)) EXPORT_FUNC (__stack_chk_fail) (void); static grub_addr_t __attribute__ ((weakref("__stack_chk_guard"))) EXPORT_VAR (_stack_chk_guard); static void __attribute__ ((noreturn, weakref("__stack_chk_fail"))) EXPORT_FUNC (_stack_chk_fail) (void); #endif + +extern grub_addr_t grub_stack_protector_init (void); + +static inline __attribute__((__always_inline__)) +void grub_update_stack_guard (void) +{ + grub_addr_t guard; + + guard = grub_stack_protector_init (); + if (guard) + __stack_chk_guard = guard; +} #endif #endif /* GRUB_STACK_PROTECTOR_H */