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 505c8a1ccbe0cd043d672a8e1192e052ac73d84a..7e3a9cf2193d9e99500ff52908513054281a0d7d 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 5e56d26a223983546b383cdb90f4a2fbd5027833..7868a176993f4dcd3b2585865232dfe014dcb02e 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 094701ec5500b431094b9a6fafcae4bbdb6e2e10..dbba4b7559aa0db9f45ab7531416f104a50644ff 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 839291430cb3be6ca4f2b825ccc22e5446de1d4d..4c0ea3cd4ea406b63d711c257fc9f04fc8437068 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 45131e354e27f1f8fc6607e173638c65c2d40f5b..4c13dafc98b8400f51468c880a2513242b65b669 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 be0a2bc3e20d02442f503857254a959b7df636ba..530347cdebe3aa489095116a66d204b20abf7ba5 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 b1601aad7e1a8d66eb1888454bb866bc7c5d8c4c..1016f0b5311d6e4b5576c7ba1c44e909217e5d2b 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 d06ada2341cb9e2fdcdbd07a846646b8d94856f9..0cca179e510649b1e719715d0c7f0a2dc19056ca 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 da4bddd261717bf336c1e0efdb5338f738fc7cad..bf5bcf2836d8152ec8a940e7c7f59baabe0da1b5 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)