[PATCH v3 1/3] arm64: unwind: add asynchronous unwind tables to kernel and modules
Fangrui Song
maskray at google.com
Thu Jun 16 00:24:04 PDT 2022
On Thu, Jun 16, 2022 at 12:14 AM Ard Biesheuvel <ardb at kernel.org> wrote:
>
> On Wed, 15 Jun 2022 at 23:52, Fangrui Song <maskray at google.com> wrote:
> >
> > On 2022-06-15, Kees Cook wrote:
> > >On Wed, Jun 15, 2022 at 9:54 AM Ard Biesheuvel <ardb at kernel.org> wrote:
> > >>
> > >> On Wed, 15 Jun 2022 at 18:50, Sami Tolvanen <samitolvanen at 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 at kernel.org>
> > >> > > Reviewed-by: Nick Desaulniers <ndesaulniers at 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.
More information about the linux-arm-kernel
mailing list