From 518f30a84fcf54e9b9e8a5f1f3f0cb2f1a706c39 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 4 Mar 2024 08:35:45 +0100 Subject: [PATCH] rust: support for shadow call stack sanitizer This patch adds all of the flags that are needed to support the shadow call stack (SCS) sanitizer with Rust, and updates Kconfig to allow configurations that work. The -Zfixed-x18 flag is required to use SCS on arm64, and requires rustc version 1.80.0 or greater. This restriction is reflected in Kconfig. When CONFIG_DYNAMIC_SCS is enabled, the build will be configured to include unwind tables in the build artifacts. Dynamic SCS uses the unwind tables at boot to find all places that need to be patched. The -Cforce-unwind-tables=y flag ensures that unwind tables are available for Rust code. In non-dynamic mode, the -Zsanitizer=shadow-call-stack flag is what enables the SCS sanitizer. At the time of writing, all released rustc versions up to and including 1.81 incorrectly think that the Rust targets aarch64-unknown-none and riscv64-unknown-none-elf don't support -Zsanitizer=shadow-call-stack, so the build will fail if you enable shadow call stack in non-dynamic mode. See [1] for the relevant feature request. To avoid this compilation failure, Kconfig is set up to reject such configurations. Note that because these configurations are rejected, this patch only allows SCS to be used with arm64 and not on riscv. However, once [1] is implemented, I will submit a follow-up patch that allows configurations without UNWIND_PATCH_PAC_INTO_SCS on sufficiently new compilers. That patch will implicitly allow SCS to be enabled on riscv, but this is okay because unlike arm64, riscv does not need any flags for rustc beyond -Zsanitizer=shadow-call-stack. It is possible to avoid the requirement of rustc 1.80.0 by using -Ctarget-feature=+reserve-x18 instead of -Zfixed-x18. However, this flag emits a warning during the build, so this patch does not add support for using it and instead requires 1.80.0 or greater. The `depends on` clause is placed on `config RUST` to avoid a situation where enabling Rust silently turns off the sanitizer. Instead, turning on the sanitizer results in Rust being disabled. We generally do not want changes to CONFIG_RUST to result in any mitigations being changed or turned off. Link: https://github.com/rust-lang/rust/issues/121972 [1] Signed-off-by: Alice Ryhl --- Makefile | 1 + arch/arm64/Makefile | 3 +++ init/Kconfig | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 44c02a6f60a145..eb01a26d8354be 100644 --- a/Makefile +++ b/Makefile @@ -927,6 +927,7 @@ ifdef CONFIG_SHADOW_CALL_STACK ifndef CONFIG_DYNAMIC_SCS CC_FLAGS_SCS := -fsanitize=shadow-call-stack KBUILD_CFLAGS += $(CC_FLAGS_SCS) +KBUILD_RUSTFLAGS += -Zsanitizer=shadow-call-stack endif export CC_FLAGS_SCS endif diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index f6bc3da1ef110e..b058c4803efb1c 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -57,9 +57,11 @@ KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) ifneq ($(CONFIG_UNWIND_TABLES),y) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables KBUILD_AFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables +KBUILD_RUSTFLAGS += -Cforce-unwind-tables=n else KBUILD_CFLAGS += -fasynchronous-unwind-tables KBUILD_AFLAGS += -fasynchronous-unwind-tables +KBUILD_RUSTFLAGS += -Cforce-unwind-tables=y -Zuse-sync-unwind=n endif ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) @@ -114,6 +116,7 @@ endif ifeq ($(CONFIG_SHADOW_CALL_STACK), y) KBUILD_CFLAGS += -ffixed-x18 +KBUILD_RUSTFLAGS += -Zfixed-x18 endif ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) diff --git a/init/Kconfig b/init/Kconfig index fe76c5d0a72e34..d857f6f90885fd 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1909,7 +1909,7 @@ config RUST depends on !MODVERSIONS depends on !GCC_PLUGINS depends on !RANDSTRUCT - depends on !SHADOW_CALL_STACK + depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108000 && UNWIND_PATCH_PAC_INTO_SCS depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE help Enables Rust support in the kernel.