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