arm64: unwind: add asynchronous unwind tables to kernel and modules
authorArd Biesheuvel <ardb@kernel.org>
Thu, 27 Oct 2022 15:59:06 +0000 (17:59 +0200)
committerWill Deacon <will@kernel.org>
Wed, 9 Nov 2022 18:06:35 +0000 (18:06 +0000)
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>
Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Sami Tolvanen <samitolvanen@google.com>
Link: https://lore.kernel.org/r/20221027155908.1940624-2-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/Kconfig
arch/arm64/Makefile
arch/arm64/include/asm/module.lds.h
arch/arm64/kernel/pi/Makefile
arch/arm64/kernel/vmlinux.lds.S
arch/arm64/kvm/hyp/nvhe/Makefile
drivers/firmware/efi/libstub/Makefile
include/asm-generic/vmlinux.lds.h
scripts/module.lds.S

index 505c8a1..7e3a9cf 100644 (file)
@@ -370,6 +370,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"
index 5e56d26..7868a17 100644 (file)
@@ -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
index 094701e..dbba4b7 100644 (file)
@@ -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
 }
index 8392914..4c0ea3c 100644 (file)
@@ -7,6 +7,7 @@ KBUILD_CFLAGS   := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) -fpie \
                   -I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \
                   -include $(srctree)/include/linux/hidden.h \
                   -D__DISABLE_EXPORTS -ffreestanding -D__NO_FORTIFY \
+                  -fno-asynchronous-unwind-tables -fno-unwind-tables \
                   $(call cc-option,-fno-addrsig)
 
 # remove SCS flags from all objects in this directory
index 45131e3..4c13daf 100644 (file)
@@ -121,6 +121,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 = .;
index be0a2bc..530347c 100644 (file)
@@ -96,6 +96,7 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_CFI)
 # when profile optimization is applied. gen-hyprel does not support SHT_REL and
 # causes a build failure. Remove profile optimization flags.
 KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%, $(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
index b1601aa..1016f0b 100644 (file)
@@ -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 \
index d06ada2..0cca179 100644 (file)
  * keep any .init_array.* sections.
  * https://bugs.llvm.org/show_bug.cgi?id=46478
  */
+#ifdef CONFIG_UNWIND_TABLES
+#define DISCARD_EH_FRAME
+#else
+#define DISCARD_EH_FRAME       *(.eh_frame)
+#endif
 #if defined(CONFIG_GCOV_KERNEL) || defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KCSAN)
 # ifdef CONFIG_CONSTRUCTORS
 #  define SANITIZER_DISCARDS                                           \
-       *(.eh_frame)
+       DISCARD_EH_FRAME
 # else
 #  define SANITIZER_DISCARDS                                           \
        *(.init_array) *(.init_array.*)                                 \
-       *(.eh_frame)
+       DISCARD_EH_FRAME
 # endif
 #else
 # define SANITIZER_DISCARDS
index da4bddd..bf5bcf2 100644 (file)
@@ -3,6 +3,12 @@
  * Archs are free to supply their own linker scripts.  ld will
  * combine them automatically.
  */
+#ifdef CONFIG_UNWIND_TABLES
+#define DISCARD_EH_FRAME
+#else
+#define DISCARD_EH_FRAME       *(.eh_frame)
+#endif
+
 SECTIONS {
        /DISCARD/ : {
                *(.discard)