rust: support for shadow call stack sanitizer
authorAlice Ryhl <aliceryhl@google.com>
Thu, 29 Aug 2024 08:22:45 +0000 (08:22 +0000)
committerMiguel Ojeda <ojeda@kernel.org>
Thu, 12 Sep 2024 22:03:14 +0000 (00:03 +0200)
Add all of the flags that are needed to support the shadow call stack
(SCS) sanitizer with Rust, and updates Kconfig to allow only
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. Using this flag requires rustc version 1.82.0
or greater on the targets used by Rust in the kernel. This restriction
is reflected in Kconfig.

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 dependency is placed on `select HAVE_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.

At the time of writing, rustc 1.82.0 only exists via the nightly release
channel. There is a chance that the -Zsanitizer=shadow-call-stack flag
will end up needing 1.83.0 instead, but I think it is small.

Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Kees Cook <kees@kernel.org>
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240829-shadow-call-stack-v7-1-2f62a4432abf@google.com
[ Fixed indentation using spaces. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Makefile
arch/arm64/Kconfig
arch/arm64/Makefile
arch/riscv/Kconfig
init/Kconfig

index 1883aeb919a416a50da88dc169a737137a0e724a..ec9cec3b650daa19bcd106194b8c9dea5dd05634 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -929,6 +929,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
index a2f8ff354ca670af50e44c790c6c201b63aa0ddb..d56400bfd20aa09831421742153898db7e3460cb 100644 (file)
@@ -231,7 +231,7 @@ config ARM64
        select HAVE_FUNCTION_ARG_ACCESS_API
        select MMU_GATHER_RCU_TABLE_FREE
        select HAVE_RSEQ
-       select HAVE_RUST if CPU_LITTLE_ENDIAN
+       select HAVE_RUST if RUSTC_SUPPORTS_ARM64
        select HAVE_STACKPROTECTOR
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_KPROBES
@@ -265,6 +265,18 @@ config ARM64
        help
          ARM 64-bit (AArch64) Linux support.
 
+config RUSTC_SUPPORTS_ARM64
+       def_bool y
+       depends on CPU_LITTLE_ENDIAN
+       # Shadow call stack is only supported on certain rustc versions.
+       #
+       # When using the UNWIND_PATCH_PAC_INTO_SCS option, rustc version 1.80+ is
+       # required due to use of the -Zfixed-x18 flag.
+       #
+       # Otherwise, rustc version 1.82+ is required due to use of the
+       # -Zsanitizer=shadow-call-stack flag.
+       depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108200 || RUSTC_VERSION >= 108000 && UNWIND_PATCH_PAC_INTO_SCS
+
 config CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS
        def_bool CC_IS_CLANG
        # https://github.com/ClangBuiltLinux/linux/issues/1507
index f6bc3da1ef110eb2d3539cfe977823a504c4ded0..b058c4803efb1c6d97d3e3ae1942abeef26cf330 100644 (file)
@@ -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)
index 0f3cd7c3a4360529331d8dd0023c11460b957622..6d9234216c69225f54f3a5e9d1918b74340470d5 100644 (file)
@@ -172,7 +172,7 @@ config RISCV
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_RETHOOK if !XIP_KERNEL
        select HAVE_RSEQ
-       select HAVE_RUST if 64BIT
+       select HAVE_RUST if RUSTC_SUPPORTS_RISCV
        select HAVE_SAMPLE_FTRACE_DIRECT
        select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
        select HAVE_STACKPROTECTOR
@@ -202,6 +202,13 @@ config RISCV
        select UACCESS_MEMCPY if !MMU
        select ZONE_DMA32 if 64BIT
 
+config RUSTC_SUPPORTS_RISCV
+       def_bool y
+       depends on 64BIT
+       # Shadow call stack requires rustc version 1.82+ due to use of the
+       # -Zsanitizer=shadow-call-stack flag.
+       depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108200
+
 config CLANG_SUPPORTS_DYNAMIC_FTRACE
        def_bool CC_IS_CLANG
        # https://github.com/ClangBuiltLinux/linux/issues/1817
index c6b744a48dcca7d7fb5b1e87256865fcfd305375..9bcda3b0a20f5cbfdda38cae8700a958483a4d5c 100644 (file)
@@ -1909,7 +1909,6 @@ config RUST
        depends on !MODVERSIONS
        depends on !GCC_PLUGIN_RANDSTRUCT
        depends on !RANDSTRUCT
-       depends on !SHADOW_CALL_STACK
        depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
        help
          Enables Rust support in the kernel.