diff mbox series

[v3,1/3] arm64: unwind: add asynchronous unwind tables to kernel and modules

Message ID 20220613134008.3760481-2-ardb@kernel.org (mailing list archive)
State New, archived
Headers show
Series arm64: dynamic shadow call stack support | expand

Commit Message

Ard Biesheuvel June 13, 2022, 1:40 p.m. UTC
Enable asynchronous unwind table generation for both the core kernel as
well as modules, and emit the resulting .eh_frame sections as init code
so we can use the unwind directives for code patching at boot or module
load time.

This will be used by dynamic shadow call stack support, which will rely
on code patching rather than compiler codegen to emit the shadow call
stack push and pop instructions.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
---
 arch/arm64/Kconfig                    |  3 +++
 arch/arm64/Makefile                   |  5 +++++
 arch/arm64/include/asm/module.lds.h   |  8 ++++++++
 arch/arm64/kernel/vmlinux.lds.S       | 13 +++++++++++++
 arch/arm64/kvm/hyp/nvhe/Makefile      |  1 +
 drivers/firmware/efi/libstub/Makefile |  1 +
 6 files changed, 31 insertions(+)

Comments

Sami Tolvanen June 15, 2022, 4:50 p.m. UTC | #1
On Mon, Jun 13, 2022 at 03:40:06PM +0200, Ard Biesheuvel wrote:
> Enable asynchronous unwind table generation for both the core kernel as
> well as modules, and emit the resulting .eh_frame sections as init code
> so we can use the unwind directives for code patching at boot or module
> load time.
> 
> This will be used by dynamic shadow call stack support, which will rely
> on code patching rather than compiler codegen to emit the shadow call
> stack push and pop instructions.
> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> ---
>  arch/arm64/Kconfig                    |  3 +++
>  arch/arm64/Makefile                   |  5 +++++
>  arch/arm64/include/asm/module.lds.h   |  8 ++++++++
>  arch/arm64/kernel/vmlinux.lds.S       | 13 +++++++++++++
>  arch/arm64/kvm/hyp/nvhe/Makefile      |  1 +
>  drivers/firmware/efi/libstub/Makefile |  1 +
>  6 files changed, 31 insertions(+)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 1652a9800ebe..5f92344edff5 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -366,6 +366,9 @@ config KASAN_SHADOW_OFFSET
>  	default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
>  	default 0xffffffffffffffff
>  
> +config UNWIND_TABLES
> +	bool
> +
>  source "arch/arm64/Kconfig.platforms"
>  
>  menu "Kernel Features"
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 6d9d4a58b898..4fbca56fa602 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -45,8 +45,13 @@ KBUILD_CFLAGS	+= $(call cc-option,-mabi=lp64)
>  KBUILD_AFLAGS	+= $(call cc-option,-mabi=lp64)
>  
>  # Avoid generating .eh_frame* sections.
> +ifneq ($(CONFIG_UNWIND_TABLES),y)
>  KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables -fno-unwind-tables
>  KBUILD_AFLAGS	+= -fno-asynchronous-unwind-tables -fno-unwind-tables
> +else
> +KBUILD_CFLAGS	+= -fasynchronous-unwind-tables
> +KBUILD_AFLAGS	+= -fasynchronous-unwind-tables
> +endif
>  
>  ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
>  prepare: stack_protector_prepare
> diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
> index 094701ec5500..dbba4b7559aa 100644
> --- a/arch/arm64/include/asm/module.lds.h
> +++ b/arch/arm64/include/asm/module.lds.h
> @@ -17,4 +17,12 @@ SECTIONS {
>  	 */
>  	.text.hot : { *(.text.hot) }
>  #endif
> +
> +#ifdef CONFIG_UNWIND_TABLES
> +	/*
> +	 * Currently, we only use unwind info at module load time, so we can
> +	 * put it into the .init allocation.
> +	 */
> +	.init.eh_frame : { *(.eh_frame) }
> +#endif
>  }
> diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> index 2d4a8f995175..7bf4809f523d 100644
> --- a/arch/arm64/kernel/vmlinux.lds.S
> +++ b/arch/arm64/kernel/vmlinux.lds.S
> @@ -120,6 +120,17 @@ jiffies = jiffies_64;
>  #define TRAMP_TEXT
>  #endif
>  
> +#ifdef CONFIG_UNWIND_TABLES
> +#define UNWIND_DATA_SECTIONS				\
> +	.eh_frame : {					\
> +		__eh_frame_start = .;			\
> +		*(.eh_frame)				\
> +		__eh_frame_end = .;			\
> +	}
> +#else
> +#define UNWIND_DATA_SECTIONS
> +#endif

How does this work with SANITIZER_DISCARDS dropping .eh_frame in
include/asm-generic/vmlinux.lds.h and scripts/module.lds.S? We would
definitely want to enable this together with CONFIG_CFI_CLANG, so it
seems like we'd have to drop the discard rules as well.

Sami
Ard Biesheuvel June 15, 2022, 4:53 p.m. UTC | #2
On Wed, 15 Jun 2022 at 18:50, Sami Tolvanen <samitolvanen@google.com> wrote:
>
> On Mon, Jun 13, 2022 at 03:40:06PM +0200, Ard Biesheuvel wrote:
> > Enable asynchronous unwind table generation for both the core kernel as
> > well as modules, and emit the resulting .eh_frame sections as init code
> > so we can use the unwind directives for code patching at boot or module
> > load time.
> >
> > This will be used by dynamic shadow call stack support, which will rely
> > on code patching rather than compiler codegen to emit the shadow call
> > stack push and pop instructions.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> > ---
> >  arch/arm64/Kconfig                    |  3 +++
> >  arch/arm64/Makefile                   |  5 +++++
> >  arch/arm64/include/asm/module.lds.h   |  8 ++++++++
> >  arch/arm64/kernel/vmlinux.lds.S       | 13 +++++++++++++
> >  arch/arm64/kvm/hyp/nvhe/Makefile      |  1 +
> >  drivers/firmware/efi/libstub/Makefile |  1 +
> >  6 files changed, 31 insertions(+)
> >
> > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > index 1652a9800ebe..5f92344edff5 100644
> > --- a/arch/arm64/Kconfig
> > +++ b/arch/arm64/Kconfig
> > @@ -366,6 +366,9 @@ config KASAN_SHADOW_OFFSET
> >       default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
> >       default 0xffffffffffffffff
> >
> > +config UNWIND_TABLES
> > +     bool
> > +
> >  source "arch/arm64/Kconfig.platforms"
> >
> >  menu "Kernel Features"
> > diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> > index 6d9d4a58b898..4fbca56fa602 100644
> > --- a/arch/arm64/Makefile
> > +++ b/arch/arm64/Makefile
> > @@ -45,8 +45,13 @@ KBUILD_CFLAGS      += $(call cc-option,-mabi=lp64)
> >  KBUILD_AFLAGS        += $(call cc-option,-mabi=lp64)
> >
> >  # Avoid generating .eh_frame* sections.
> > +ifneq ($(CONFIG_UNWIND_TABLES),y)
> >  KBUILD_CFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
> >  KBUILD_AFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
> > +else
> > +KBUILD_CFLAGS        += -fasynchronous-unwind-tables
> > +KBUILD_AFLAGS        += -fasynchronous-unwind-tables
> > +endif
> >
> >  ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
> >  prepare: stack_protector_prepare
> > diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
> > index 094701ec5500..dbba4b7559aa 100644
> > --- a/arch/arm64/include/asm/module.lds.h
> > +++ b/arch/arm64/include/asm/module.lds.h
> > @@ -17,4 +17,12 @@ SECTIONS {
> >        */
> >       .text.hot : { *(.text.hot) }
> >  #endif
> > +
> > +#ifdef CONFIG_UNWIND_TABLES
> > +     /*
> > +      * Currently, we only use unwind info at module load time, so we can
> > +      * put it into the .init allocation.
> > +      */
> > +     .init.eh_frame : { *(.eh_frame) }
> > +#endif
> >  }
> > diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> > index 2d4a8f995175..7bf4809f523d 100644
> > --- a/arch/arm64/kernel/vmlinux.lds.S
> > +++ b/arch/arm64/kernel/vmlinux.lds.S
> > @@ -120,6 +120,17 @@ jiffies = jiffies_64;
> >  #define TRAMP_TEXT
> >  #endif
> >
> > +#ifdef CONFIG_UNWIND_TABLES
> > +#define UNWIND_DATA_SECTIONS                         \
> > +     .eh_frame : {                                   \
> > +             __eh_frame_start = .;                   \
> > +             *(.eh_frame)                            \
> > +             __eh_frame_end = .;                     \
> > +     }
> > +#else
> > +#define UNWIND_DATA_SECTIONS
> > +#endif
>
> How does this work with SANITIZER_DISCARDS dropping .eh_frame in
> include/asm-generic/vmlinux.lds.h and scripts/module.lds.S? We would
> definitely want to enable this together with CONFIG_CFI_CLANG, so it
> seems like we'd have to drop the discard rules as well.
>

Good point, I had no idea that that existed.

Clang 13 should have the fix for the original issue, so we could make
this workaround specific to 12 and earlier.
Kees Cook June 15, 2022, 9:29 p.m. UTC | #3
On Wed, Jun 15, 2022 at 9:54 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Wed, 15 Jun 2022 at 18:50, Sami Tolvanen <samitolvanen@google.com> wrote:
> >
> > On Mon, Jun 13, 2022 at 03:40:06PM +0200, Ard Biesheuvel wrote:
> > > Enable asynchronous unwind table generation for both the core kernel as
> > > well as modules, and emit the resulting .eh_frame sections as init code
> > > so we can use the unwind directives for code patching at boot or module
> > > load time.
> > >
> > > This will be used by dynamic shadow call stack support, which will rely
> > > on code patching rather than compiler codegen to emit the shadow call
> > > stack push and pop instructions.
> > >
> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > > Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> > > ---
> > >  arch/arm64/Kconfig                    |  3 +++
> > >  arch/arm64/Makefile                   |  5 +++++
> > >  arch/arm64/include/asm/module.lds.h   |  8 ++++++++
> > >  arch/arm64/kernel/vmlinux.lds.S       | 13 +++++++++++++
> > >  arch/arm64/kvm/hyp/nvhe/Makefile      |  1 +
> > >  drivers/firmware/efi/libstub/Makefile |  1 +
> > >  6 files changed, 31 insertions(+)
> > >
> > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > > index 1652a9800ebe..5f92344edff5 100644
> > > --- a/arch/arm64/Kconfig
> > > +++ b/arch/arm64/Kconfig
> > > @@ -366,6 +366,9 @@ config KASAN_SHADOW_OFFSET
> > >       default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
> > >       default 0xffffffffffffffff
> > >
> > > +config UNWIND_TABLES
> > > +     bool
> > > +
> > >  source "arch/arm64/Kconfig.platforms"
> > >
> > >  menu "Kernel Features"
> > > diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> > > index 6d9d4a58b898..4fbca56fa602 100644
> > > --- a/arch/arm64/Makefile
> > > +++ b/arch/arm64/Makefile
> > > @@ -45,8 +45,13 @@ KBUILD_CFLAGS      += $(call cc-option,-mabi=lp64)
> > >  KBUILD_AFLAGS        += $(call cc-option,-mabi=lp64)
> > >
> > >  # Avoid generating .eh_frame* sections.
> > > +ifneq ($(CONFIG_UNWIND_TABLES),y)
> > >  KBUILD_CFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
> > >  KBUILD_AFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
> > > +else
> > > +KBUILD_CFLAGS        += -fasynchronous-unwind-tables
> > > +KBUILD_AFLAGS        += -fasynchronous-unwind-tables
> > > +endif
> > >
> > >  ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
> > >  prepare: stack_protector_prepare
> > > diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
> > > index 094701ec5500..dbba4b7559aa 100644
> > > --- a/arch/arm64/include/asm/module.lds.h
> > > +++ b/arch/arm64/include/asm/module.lds.h
> > > @@ -17,4 +17,12 @@ SECTIONS {
> > >        */
> > >       .text.hot : { *(.text.hot) }
> > >  #endif
> > > +
> > > +#ifdef CONFIG_UNWIND_TABLES
> > > +     /*
> > > +      * Currently, we only use unwind info at module load time, so we can
> > > +      * put it into the .init allocation.
> > > +      */
> > > +     .init.eh_frame : { *(.eh_frame) }
> > > +#endif
> > >  }
> > > diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> > > index 2d4a8f995175..7bf4809f523d 100644
> > > --- a/arch/arm64/kernel/vmlinux.lds.S
> > > +++ b/arch/arm64/kernel/vmlinux.lds.S
> > > @@ -120,6 +120,17 @@ jiffies = jiffies_64;
> > >  #define TRAMP_TEXT
> > >  #endif
> > >
> > > +#ifdef CONFIG_UNWIND_TABLES
> > > +#define UNWIND_DATA_SECTIONS                         \
> > > +     .eh_frame : {                                   \
> > > +             __eh_frame_start = .;                   \
> > > +             *(.eh_frame)                            \
> > > +             __eh_frame_end = .;                     \
> > > +     }
> > > +#else
> > > +#define UNWIND_DATA_SECTIONS
> > > +#endif
> >
> > How does this work with SANITIZER_DISCARDS dropping .eh_frame in
> > include/asm-generic/vmlinux.lds.h and scripts/module.lds.S? We would
> > definitely want to enable this together with CONFIG_CFI_CLANG, so it
> > seems like we'd have to drop the discard rules as well.
> >
>
> Good point, I had no idea that that existed.
>
> Clang 13 should have the fix for the original issue, so we could make
> this workaround specific to 12 and earlier.

Yeah, I like this -- I'd prefer to know when we get "surprise" sections again.
Fangrui Song June 15, 2022, 9:52 p.m. UTC | #4
On 2022-06-15, Kees Cook wrote:
>On Wed, Jun 15, 2022 at 9:54 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>>
>> On Wed, 15 Jun 2022 at 18:50, Sami Tolvanen <samitolvanen@google.com> wrote:
>> >
>> > On Mon, Jun 13, 2022 at 03:40:06PM +0200, Ard Biesheuvel wrote:
>> > > Enable asynchronous unwind table generation for both the core kernel as
>> > > well as modules, and emit the resulting .eh_frame sections as init code
>> > > so we can use the unwind directives for code patching at boot or module
>> > > load time.
>> > >
>> > > This will be used by dynamic shadow call stack support, which will rely
>> > > on code patching rather than compiler codegen to emit the shadow call
>> > > stack push and pop instructions.
>> > >
>> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>> > > Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
>> > > ---
>> > >  arch/arm64/Kconfig                    |  3 +++
>> > >  arch/arm64/Makefile                   |  5 +++++
>> > >  arch/arm64/include/asm/module.lds.h   |  8 ++++++++
>> > >  arch/arm64/kernel/vmlinux.lds.S       | 13 +++++++++++++
>> > >  arch/arm64/kvm/hyp/nvhe/Makefile      |  1 +
>> > >  drivers/firmware/efi/libstub/Makefile |  1 +
>> > >  6 files changed, 31 insertions(+)
>> > >
>> > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> > > index 1652a9800ebe..5f92344edff5 100644
>> > > --- a/arch/arm64/Kconfig
>> > > +++ b/arch/arm64/Kconfig
>> > > @@ -366,6 +366,9 @@ config KASAN_SHADOW_OFFSET
>> > >       default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
>> > >       default 0xffffffffffffffff
>> > >
>> > > +config UNWIND_TABLES
>> > > +     bool
>> > > +
>> > >  source "arch/arm64/Kconfig.platforms"
>> > >
>> > >  menu "Kernel Features"
>> > > diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
>> > > index 6d9d4a58b898..4fbca56fa602 100644
>> > > --- a/arch/arm64/Makefile
>> > > +++ b/arch/arm64/Makefile
>> > > @@ -45,8 +45,13 @@ KBUILD_CFLAGS      += $(call cc-option,-mabi=lp64)
>> > >  KBUILD_AFLAGS        += $(call cc-option,-mabi=lp64)
>> > >
>> > >  # Avoid generating .eh_frame* sections.
>> > > +ifneq ($(CONFIG_UNWIND_TABLES),y)
>> > >  KBUILD_CFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
>> > >  KBUILD_AFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
>> > > +else
>> > > +KBUILD_CFLAGS        += -fasynchronous-unwind-tables
>> > > +KBUILD_AFLAGS        += -fasynchronous-unwind-tables
>> > > +endif
>> > >
>> > >  ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
>> > >  prepare: stack_protector_prepare
>> > > diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
>> > > index 094701ec5500..dbba4b7559aa 100644
>> > > --- a/arch/arm64/include/asm/module.lds.h
>> > > +++ b/arch/arm64/include/asm/module.lds.h
>> > > @@ -17,4 +17,12 @@ SECTIONS {
>> > >        */
>> > >       .text.hot : { *(.text.hot) }
>> > >  #endif
>> > > +
>> > > +#ifdef CONFIG_UNWIND_TABLES
>> > > +     /*
>> > > +      * Currently, we only use unwind info at module load time, so we can
>> > > +      * put it into the .init allocation.
>> > > +      */
>> > > +     .init.eh_frame : { *(.eh_frame) }
>> > > +#endif
>> > >  }
>> > > diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
>> > > index 2d4a8f995175..7bf4809f523d 100644
>> > > --- a/arch/arm64/kernel/vmlinux.lds.S
>> > > +++ b/arch/arm64/kernel/vmlinux.lds.S
>> > > @@ -120,6 +120,17 @@ jiffies = jiffies_64;
>> > >  #define TRAMP_TEXT
>> > >  #endif
>> > >
>> > > +#ifdef CONFIG_UNWIND_TABLES
>> > > +#define UNWIND_DATA_SECTIONS                         \
>> > > +     .eh_frame : {                                   \
>> > > +             __eh_frame_start = .;                   \
>> > > +             *(.eh_frame)                            \
>> > > +             __eh_frame_end = .;                     \
>> > > +     }
>> > > +#else
>> > > +#define UNWIND_DATA_SECTIONS
>> > > +#endif

How do you intend to use the encapsulation symbols __eh_frame_start
and __eh_frame_end ?

>> > How does this work with SANITIZER_DISCARDS dropping .eh_frame in
>> > include/asm-generic/vmlinux.lds.h and scripts/module.lds.S? We would
>> > definitely want to enable this together with CONFIG_CFI_CLANG, so it
>> > seems like we'd have to drop the discard rules as well.
>> >
>>
>> Good point, I had no idea that that existed.
>>
>> Clang 13 should have the fix for the original issue, so we could make
>> this workaround specific to 12 and earlier.
>
>Yeah, I like this -- I'd prefer to know when we get "surprise" sections again.

Does this need asynchronous unwind tables or just synchronous unwind
tables?

Note: with Clang < 15, the AArch64 codegen was in a quite bad state. It
has significantly improved since the https://reviews.llvm.org/D114545 patch series
but I am not confident to state that production use may not into an issue :-)
Ard Biesheuvel June 16, 2022, 7:14 a.m. UTC | #5
On Wed, 15 Jun 2022 at 23:52, Fangrui Song <maskray@google.com> wrote:
>
> On 2022-06-15, Kees Cook wrote:
> >On Wed, Jun 15, 2022 at 9:54 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> >>
> >> On Wed, 15 Jun 2022 at 18:50, Sami Tolvanen <samitolvanen@google.com> wrote:
> >> >
> >> > On Mon, Jun 13, 2022 at 03:40:06PM +0200, Ard Biesheuvel wrote:
> >> > > Enable asynchronous unwind table generation for both the core kernel as
> >> > > well as modules, and emit the resulting .eh_frame sections as init code
> >> > > so we can use the unwind directives for code patching at boot or module
> >> > > load time.
> >> > >
> >> > > This will be used by dynamic shadow call stack support, which will rely
> >> > > on code patching rather than compiler codegen to emit the shadow call
> >> > > stack push and pop instructions.
> >> > >
> >> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >> > > Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> >> > > ---
> >> > >  arch/arm64/Kconfig                    |  3 +++
> >> > >  arch/arm64/Makefile                   |  5 +++++
> >> > >  arch/arm64/include/asm/module.lds.h   |  8 ++++++++
> >> > >  arch/arm64/kernel/vmlinux.lds.S       | 13 +++++++++++++
> >> > >  arch/arm64/kvm/hyp/nvhe/Makefile      |  1 +
> >> > >  drivers/firmware/efi/libstub/Makefile |  1 +
> >> > >  6 files changed, 31 insertions(+)
> >> > >
> >> > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> >> > > index 1652a9800ebe..5f92344edff5 100644
> >> > > --- a/arch/arm64/Kconfig
> >> > > +++ b/arch/arm64/Kconfig
> >> > > @@ -366,6 +366,9 @@ config KASAN_SHADOW_OFFSET
> >> > >       default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
> >> > >       default 0xffffffffffffffff
> >> > >
> >> > > +config UNWIND_TABLES
> >> > > +     bool
> >> > > +
> >> > >  source "arch/arm64/Kconfig.platforms"
> >> > >
> >> > >  menu "Kernel Features"
> >> > > diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> >> > > index 6d9d4a58b898..4fbca56fa602 100644
> >> > > --- a/arch/arm64/Makefile
> >> > > +++ b/arch/arm64/Makefile
> >> > > @@ -45,8 +45,13 @@ KBUILD_CFLAGS      += $(call cc-option,-mabi=lp64)
> >> > >  KBUILD_AFLAGS        += $(call cc-option,-mabi=lp64)
> >> > >
> >> > >  # Avoid generating .eh_frame* sections.
> >> > > +ifneq ($(CONFIG_UNWIND_TABLES),y)
> >> > >  KBUILD_CFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
> >> > >  KBUILD_AFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
> >> > > +else
> >> > > +KBUILD_CFLAGS        += -fasynchronous-unwind-tables
> >> > > +KBUILD_AFLAGS        += -fasynchronous-unwind-tables
> >> > > +endif
> >> > >
> >> > >  ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
> >> > >  prepare: stack_protector_prepare
> >> > > diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
> >> > > index 094701ec5500..dbba4b7559aa 100644
> >> > > --- a/arch/arm64/include/asm/module.lds.h
> >> > > +++ b/arch/arm64/include/asm/module.lds.h
> >> > > @@ -17,4 +17,12 @@ SECTIONS {
> >> > >        */
> >> > >       .text.hot : { *(.text.hot) }
> >> > >  #endif
> >> > > +
> >> > > +#ifdef CONFIG_UNWIND_TABLES
> >> > > +     /*
> >> > > +      * Currently, we only use unwind info at module load time, so we can
> >> > > +      * put it into the .init allocation.
> >> > > +      */
> >> > > +     .init.eh_frame : { *(.eh_frame) }
> >> > > +#endif
> >> > >  }
> >> > > diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> >> > > index 2d4a8f995175..7bf4809f523d 100644
> >> > > --- a/arch/arm64/kernel/vmlinux.lds.S
> >> > > +++ b/arch/arm64/kernel/vmlinux.lds.S
> >> > > @@ -120,6 +120,17 @@ jiffies = jiffies_64;
> >> > >  #define TRAMP_TEXT
> >> > >  #endif
> >> > >
> >> > > +#ifdef CONFIG_UNWIND_TABLES
> >> > > +#define UNWIND_DATA_SECTIONS                         \
> >> > > +     .eh_frame : {                                   \
> >> > > +             __eh_frame_start = .;                   \
> >> > > +             *(.eh_frame)                            \
> >> > > +             __eh_frame_end = .;                     \
> >> > > +     }
> >> > > +#else
> >> > > +#define UNWIND_DATA_SECTIONS
> >> > > +#endif
>
> How do you intend to use the encapsulation symbols __eh_frame_start
> and __eh_frame_end ?
>

They are used in patch #3 to access the contents of the section from
the program itself.

> >> > How does this work with SANITIZER_DISCARDS dropping .eh_frame in
> >> > include/asm-generic/vmlinux.lds.h and scripts/module.lds.S? We would
> >> > definitely want to enable this together with CONFIG_CFI_CLANG, so it
> >> > seems like we'd have to drop the discard rules as well.
> >> >
> >>
> >> Good point, I had no idea that that existed.
> >>
> >> Clang 13 should have the fix for the original issue, so we could make
> >> this workaround specific to 12 and earlier.
> >
> >Yeah, I like this -- I'd prefer to know when we get "surprise" sections again.
>
> Does this need asynchronous unwind tables or just synchronous unwind
> tables?
>

I would assume that unwind tables that are only intended for
synchronous unwinding may not be instruction accurate when it comes to
the placement of the DW_CFA_negate_ra_state opcodes.

> Note: with Clang < 15, the AArch64 codegen was in a quite bad state. It
> has significantly improved since the https://reviews.llvm.org/D114545 patch series
> but I am not confident to state that production use may not into an issue :-)

This is why the feature is only enabled for Clang 15 or later.
Fangrui Song June 16, 2022, 7:24 a.m. UTC | #6
On Thu, Jun 16, 2022 at 12:14 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Wed, 15 Jun 2022 at 23:52, Fangrui Song <maskray@google.com> wrote:
> >
> > On 2022-06-15, Kees Cook wrote:
> > >On Wed, Jun 15, 2022 at 9:54 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> > >>
> > >> On Wed, 15 Jun 2022 at 18:50, Sami Tolvanen <samitolvanen@google.com> wrote:
> > >> >
> > >> > On Mon, Jun 13, 2022 at 03:40:06PM +0200, Ard Biesheuvel wrote:
> > >> > > Enable asynchronous unwind table generation for both the core kernel as
> > >> > > well as modules, and emit the resulting .eh_frame sections as init code
> > >> > > so we can use the unwind directives for code patching at boot or module
> > >> > > load time.
> > >> > >
> > >> > > This will be used by dynamic shadow call stack support, which will rely
> > >> > > on code patching rather than compiler codegen to emit the shadow call
> > >> > > stack push and pop instructions.
> > >> > >
> > >> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > >> > > Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> > >> > > ---
> > >> > >  arch/arm64/Kconfig                    |  3 +++
> > >> > >  arch/arm64/Makefile                   |  5 +++++
> > >> > >  arch/arm64/include/asm/module.lds.h   |  8 ++++++++
> > >> > >  arch/arm64/kernel/vmlinux.lds.S       | 13 +++++++++++++
> > >> > >  arch/arm64/kvm/hyp/nvhe/Makefile      |  1 +
> > >> > >  drivers/firmware/efi/libstub/Makefile |  1 +
> > >> > >  6 files changed, 31 insertions(+)
> > >> > >
> > >> > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > >> > > index 1652a9800ebe..5f92344edff5 100644
> > >> > > --- a/arch/arm64/Kconfig
> > >> > > +++ b/arch/arm64/Kconfig
> > >> > > @@ -366,6 +366,9 @@ config KASAN_SHADOW_OFFSET
> > >> > >       default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
> > >> > >       default 0xffffffffffffffff
> > >> > >
> > >> > > +config UNWIND_TABLES
> > >> > > +     bool
> > >> > > +
> > >> > >  source "arch/arm64/Kconfig.platforms"
> > >> > >
> > >> > >  menu "Kernel Features"
> > >> > > diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> > >> > > index 6d9d4a58b898..4fbca56fa602 100644
> > >> > > --- a/arch/arm64/Makefile
> > >> > > +++ b/arch/arm64/Makefile
> > >> > > @@ -45,8 +45,13 @@ KBUILD_CFLAGS      += $(call cc-option,-mabi=lp64)
> > >> > >  KBUILD_AFLAGS        += $(call cc-option,-mabi=lp64)
> > >> > >
> > >> > >  # Avoid generating .eh_frame* sections.
> > >> > > +ifneq ($(CONFIG_UNWIND_TABLES),y)
> > >> > >  KBUILD_CFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
> > >> > >  KBUILD_AFLAGS        += -fno-asynchronous-unwind-tables -fno-unwind-tables
> > >> > > +else
> > >> > > +KBUILD_CFLAGS        += -fasynchronous-unwind-tables
> > >> > > +KBUILD_AFLAGS        += -fasynchronous-unwind-tables
> > >> > > +endif
> > >> > >
> > >> > >  ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
> > >> > >  prepare: stack_protector_prepare
> > >> > > diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
> > >> > > index 094701ec5500..dbba4b7559aa 100644
> > >> > > --- a/arch/arm64/include/asm/module.lds.h
> > >> > > +++ b/arch/arm64/include/asm/module.lds.h
> > >> > > @@ -17,4 +17,12 @@ SECTIONS {
> > >> > >        */
> > >> > >       .text.hot : { *(.text.hot) }
> > >> > >  #endif
> > >> > > +
> > >> > > +#ifdef CONFIG_UNWIND_TABLES
> > >> > > +     /*
> > >> > > +      * Currently, we only use unwind info at module load time, so we can
> > >> > > +      * put it into the .init allocation.
> > >> > > +      */
> > >> > > +     .init.eh_frame : { *(.eh_frame) }
> > >> > > +#endif
> > >> > >  }
> > >> > > diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> > >> > > index 2d4a8f995175..7bf4809f523d 100644
> > >> > > --- a/arch/arm64/kernel/vmlinux.lds.S
> > >> > > +++ b/arch/arm64/kernel/vmlinux.lds.S
> > >> > > @@ -120,6 +120,17 @@ jiffies = jiffies_64;
> > >> > >  #define TRAMP_TEXT
> > >> > >  #endif
> > >> > >
> > >> > > +#ifdef CONFIG_UNWIND_TABLES
> > >> > > +#define UNWIND_DATA_SECTIONS                         \
> > >> > > +     .eh_frame : {                                   \
> > >> > > +             __eh_frame_start = .;                   \
> > >> > > +             *(.eh_frame)                            \
> > >> > > +             __eh_frame_end = .;                     \
> > >> > > +     }
> > >> > > +#else
> > >> > > +#define UNWIND_DATA_SECTIONS
> > >> > > +#endif
> >
> > How do you intend to use the encapsulation symbols __eh_frame_start
> > and __eh_frame_end ?
> >
>
> They are used in patch #3 to access the contents of the section from
> the program itself.
>
> > >> > How does this work with SANITIZER_DISCARDS dropping .eh_frame in
> > >> > include/asm-generic/vmlinux.lds.h and scripts/module.lds.S? We would
> > >> > definitely want to enable this together with CONFIG_CFI_CLANG, so it
> > >> > seems like we'd have to drop the discard rules as well.
> > >> >
> > >>
> > >> Good point, I had no idea that that existed.
> > >>
> > >> Clang 13 should have the fix for the original issue, so we could make
> > >> this workaround specific to 12 and earlier.
> > >
> > >Yeah, I like this -- I'd prefer to know when we get "surprise" sections again.
> >
> > Does this need asynchronous unwind tables or just synchronous unwind
> > tables?
> >
>
> I would assume that unwind tables that are only intended for
> synchronous unwinding may not be instruction accurate when it comes to
> the placement of the DW_CFA_negate_ra_state opcodes.
>
> > Note: with Clang < 15, the AArch64 codegen was in a quite bad state. It
> > has significantly improved since the https://reviews.llvm.org/D114545 patch series
> > but I am not confident to state that production use may not into an issue :-)
>
> This is why the feature is only enabled for Clang 15 or later.

Ok, thanks for the clarification.
diff mbox series

Patch

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1652a9800ebe..5f92344edff5 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -366,6 +366,9 @@  config KASAN_SHADOW_OFFSET
 	default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
 	default 0xffffffffffffffff
 
+config UNWIND_TABLES
+	bool
+
 source "arch/arm64/Kconfig.platforms"
 
 menu "Kernel Features"
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 6d9d4a58b898..4fbca56fa602 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -45,8 +45,13 @@  KBUILD_CFLAGS	+= $(call cc-option,-mabi=lp64)
 KBUILD_AFLAGS	+= $(call cc-option,-mabi=lp64)
 
 # Avoid generating .eh_frame* sections.
+ifneq ($(CONFIG_UNWIND_TABLES),y)
 KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables -fno-unwind-tables
 KBUILD_AFLAGS	+= -fno-asynchronous-unwind-tables -fno-unwind-tables
+else
+KBUILD_CFLAGS	+= -fasynchronous-unwind-tables
+KBUILD_AFLAGS	+= -fasynchronous-unwind-tables
+endif
 
 ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
 prepare: stack_protector_prepare
diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
index 094701ec5500..dbba4b7559aa 100644
--- a/arch/arm64/include/asm/module.lds.h
+++ b/arch/arm64/include/asm/module.lds.h
@@ -17,4 +17,12 @@  SECTIONS {
 	 */
 	.text.hot : { *(.text.hot) }
 #endif
+
+#ifdef CONFIG_UNWIND_TABLES
+	/*
+	 * Currently, we only use unwind info at module load time, so we can
+	 * put it into the .init allocation.
+	 */
+	.init.eh_frame : { *(.eh_frame) }
+#endif
 }
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 2d4a8f995175..7bf4809f523d 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -120,6 +120,17 @@  jiffies = jiffies_64;
 #define TRAMP_TEXT
 #endif
 
+#ifdef CONFIG_UNWIND_TABLES
+#define UNWIND_DATA_SECTIONS				\
+	.eh_frame : {					\
+		__eh_frame_start = .;			\
+		*(.eh_frame)				\
+		__eh_frame_end = .;			\
+	}
+#else
+#define UNWIND_DATA_SECTIONS
+#endif
+
 /*
  * The size of the PE/COFF section that covers the kernel image, which
  * runs from _stext to _edata, must be a round multiple of the PE/COFF
@@ -231,6 +242,8 @@  SECTIONS
 		__alt_instructions_end = .;
 	}
 
+	UNWIND_DATA_SECTIONS
+
 	. = ALIGN(SEGMENT_ALIGN);
 	__inittext_end = .;
 	__initdata_begin = .;
diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile
index f9fe4dc21b1f..23de41479495 100644
--- a/arch/arm64/kvm/hyp/nvhe/Makefile
+++ b/arch/arm64/kvm/hyp/nvhe/Makefile
@@ -84,6 +84,7 @@  quiet_cmd_hypcopy = HYPCOPY $@
 # Remove ftrace, Shadow Call Stack, and CFI CFLAGS.
 # This is equivalent to the 'notrace', '__noscs', and '__nocfi' annotations.
 KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_CFI), $(KBUILD_CFLAGS))
+KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
 
 # KVM nVHE code is run at a different exception code with a different map, so
 # compiler instrumentation that inserts callbacks or checks into the code may
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index d0537573501e..78c46638707a 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -20,6 +20,7 @@  cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ \
 # disable the stackleak plugin
 cflags-$(CONFIG_ARM64)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
 				   -fpie $(DISABLE_STACKLEAK_PLUGIN) \
+				   -fno-unwind-tables -fno-asynchronous-unwind-tables \
 				   $(call cc-option,-mbranch-protection=none)
 cflags-$(CONFIG_ARM)		:= $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
 				   -fno-builtin -fpic \