diff --git a/config.h.in b/config.h.in index 4d1e50eba..9b1d39971 100644 --- a/config.h.in +++ b/config.h.in @@ -64,6 +64,8 @@ # define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" # define GRUB_PLATFORM "@GRUB_PLATFORM@" +# define GRUB_STACK_PROTECTOR_INIT @GRUB_STACK_PROTECTOR_INIT@ + # define RE_ENABLE_I18N 1 # define _GNU_SOURCE 1 diff --git a/configure.ac b/configure.ac index c1b98b13d..b8c5c78d5 100644 --- a/configure.ac +++ b/configure.ac @@ -1438,6 +1438,26 @@ else AC_MSG_ERROR([invalid value $enable_stack_protector for --enable-stack-protector]) fi TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DGRUB_STACK_PROTECTOR=1" + + if test -r /dev/urandom; then + # Generate the 8 byte stack protector canary at build time if /dev/urandom + # is able to be read. The first byte should be NUL to filter out string + # buffer overflow attacks. + GRUB_STACK_PROTECTOR_INIT="$($PYTHON -c 'import codecs; rf=open("/dev/urandom", "rb"); print("0x00"+codecs.encode(rf.read(7), "hex").decode("ascii"))')" + else + # Some hosts may not have a urandom, e.g. Windows, so use statically + # generated random bytes + GRUB_STACK_PROTECTOR_INIT="0x00f2b7e2f193b25c" + fi + + if test x"$target_m32" = x1 ; then + # Make sure that the canary default value is 24-bits by only using the + # lower 3 bytes on 32 bit systems. This allows the upper byte to be NUL + # to filter out string buffer overflow attacks. + GRUB_STACK_PROTECTOR_INIT="0x00$(echo "$GRUB_STACK_PROTECTOR_INIT" | sed 's/.*\(......\)$/\1/')" + fi + + AC_SUBST([GRUB_STACK_PROTECTOR_INIT]) fi CFLAGS="$TARGET_CFLAGS" diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 08e24d46f..6c54af6e7 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -46,7 +46,7 @@ static grub_guid_t rng_protocol_guid = GRUB_EFI_RNG_PROTOCOL_GUID; 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) 0x00f2b7e2f193b25c; +grub_addr_t __stack_chk_guard = (grub_addr_t) GRUB_STACK_PROTECTOR_INIT; void __attribute__ ((noreturn)) __stack_chk_fail (void)