grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v5] efi: Fix stack protector issues


From: Ard Biesheuvel
Subject: Re: [PATCH v5] efi: Fix stack protector issues
Date: Mon, 29 Apr 2024 15:03:50 +0200

On Sat, 27 Apr 2024 at 15:08, Glenn Washburn
<development@efficientek.com> wrote:
>
> From: Ard Biesheuvel <ardb@kernel.org>
>
> The 'ground truth' stack protector cookie value is kept in a global
> variable, and loaded in every function prologue and epilogue to store
> it into resp. compare it with the stack slot holding the cookie.
>
> If the comparison fails, the program aborts, and this might occur
> spuriously when the global variable changes values between the entry and
> exit of a function. This implies that assigning the global variable at
> boot should not involve any instrumented function calls, unless special
> care is taken to ensure that the live call stack is synchronized, which
> is non-trivial.
>
> So avoid any function calls, including grub_memcpy(), which is
> unnecessary given that the stack cookie is always a suitably aligned
> variable of the native word size.
>
> While at it, leave the last byte 0x0 to avoid inadvertent unbounded
> strings on the stack.
>
> Note that the use of __attribute__((optimize)) is described as
> unsuitable for production use in the GCC documentation, so let's drop
> this as well now that it is no longer needed.
>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> Reviewed-by: Glenn Washburn <development@efficientek.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Thanks for taking care of this.

I'd ack it but that would make the signoff chain look even weirder :-)


> ---
> v5:
>  * Add missing include
>
> v4:
>  * Rebase to current master
>
> v3:
>  * Add more reasoning to comment as suggested by Vladimir
>
> Range-diff against v4:
> 1:  a79252528231 ! 1:  5731e2978906 efi: Fix stack protector issues
>     @@ grub-core/kern/efi/init.c: grub_efi_init (void)
>
>
>       ## grub-core/kern/main.c ##
>     +@@
>     +  */
>     +
>     + #include <grub/kernel.h>
>     ++#include <grub/stack_protector.h>
>     + #include <grub/misc.h>
>     + #include <grub/symbol.h>
>     + #include <grub/dl.h>
>      @@ grub-core/kern/main.c: reclaim_module_space (void)
>       void __attribute__ ((noreturn))
>       grub_main (void)
>
>  grub-core/kern/efi/init.c      | 27 ++++++++-------------------
>  grub-core/kern/main.c          | 11 +++++++++++
>  include/grub/stack_protector.h | 13 +++++++++++++
>  3 files changed, 32 insertions(+), 19 deletions(-)
>
> diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
> index 6c54af6e79e5..1637077e1e96 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 731c07c2901a..744197785547 100644
> --- a/grub-core/kern/main.c
> +++ b/grub-core/kern/main.c
> @@ -18,6 +18,7 @@
>   */
>
>  #include <grub/kernel.h>
> +#include <grub/stack_protector.h>
>  #include <grub/misc.h>
>  #include <grub/symbol.h>
>  #include <grub/dl.h>
> @@ -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 13d2657d98f5..645849e52d50 100644
> --- a/include/grub/stack_protector.h
> +++ b/include/grub/stack_protector.h
> @@ -29,6 +29,19 @@ 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
> +
> +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 */
> --
> 2.34.1
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]