From f1385dc670fe66860bcec5dcba215364bf71b807 Mon Sep 17 00:00:00 2001 From: Neal Gompa Date: Wed, 31 Jul 2024 08:54:28 -0400 Subject: init/Kconfig: Only block on RANDSTRUCT for RUST When enabling Rust in the kernel, we only need to block on the RANDSTRUCT feature and GCC plugin. The rest of the GCC plugins are reasonably safe to enable. [ Originally (years ago) we only had this restriction, but we ended up restricting also the rest of the GCC plugins 1) to be on the safe side, 2) since compiler plugin support could be going away in the kernel and 3) since mixed builds are best effort so far; so I asked Neal about his experience enabling the other plugins -- Neal says: When I originally wrote this patch two years ago to get things working, Fedora used all the GCC plugins, so I was trying to get GCC + Rust to work while minimizing the delta on build differences. This was the combination that worked. We've been carrying this patch in the Asahi tree for a year now. And while Fedora does not currently have GCC plugins enabled because it caused issues with some third-party modules (I think it was the NVIDIA driver, but I'm not sure), it was around long enough for me to know with some confidence that it was fine this way. - Miguel ] Signed-off-by: Neal Gompa Link: https://lore.kernel.org/r/20240731125615.3368813-1-neal@gompa.dev Signed-off-by: Miguel Ojeda --- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'init') diff --git a/init/Kconfig b/init/Kconfig index 5783a0b87517..839c83034006 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1900,7 +1900,7 @@ config RUST depends on RUST_IS_AVAILABLE depends on !CFI_CLANG depends on !MODVERSIONS - depends on !GCC_PLUGINS + depends on !GCC_PLUGIN_RANDSTRUCT depends on !RANDSTRUCT depends on !SHADOW_CALL_STACK depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE -- cgit v1.2.3 From 6e74c6b5a42e6a7313fcd29e814f211b392a00f5 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 2 Sep 2024 18:55:28 +0200 Subject: kbuild: rust: add `CONFIG_RUSTC_VERSION` Now that we support several Rust versions, introduce `CONFIG_RUSTC_VERSION` so that it can be used in Kconfig to enable and disable configuration options based on the `rustc` version. The approach taken resembles `pahole`'s -- see commit 613fe1692377 ("kbuild: Add CONFIG_PAHOLE_VERSION"), i.e. a simple version parsing without trying to identify several kinds of compilers, since so far there is only one (`rustc`). However, unlike `pahole`'s, we also print a zero if executing failed for any reason, rather than checking if the command is found and executable (which still leaves things like a file that exists and is executable, but e.g. is built for another platform [1]). An equivalent approach to the one here was also submitted for `pahole` [2]. Link: https://lore.kernel.org/rust-for-linux/CANiq72=4vX_tJMJLE6e+bg7ZECHkS-AQpm8GBzuK75G1EB7+Nw@mail.gmail.com/ [1] Link: https://lore.kernel.org/linux-kbuild/20240728125527.690726-1-ojeda@kernel.org/ [2] Reviewed-by: Nicolas Schier Tested-by: Alice Ryhl Acked-by: Masahiro Yamada Link: https://lore.kernel.org/r/20240902165535.1101978-2-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- init/Kconfig | 7 +++++++ scripts/rustc-version.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100755 scripts/rustc-version.sh (limited to 'init') diff --git a/init/Kconfig b/init/Kconfig index 839c83034006..38c1cfcce821 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -60,6 +60,13 @@ config LLD_VERSION default $(ld-version) if LD_IS_LLD default 0 +config RUSTC_VERSION + int + default $(shell,$(srctree)/scripts/rustc-version.sh $(RUSTC)) + help + It does not depend on `RUST` since that one may need to use the version + in a `depends on`. + config RUST_IS_AVAILABLE def_bool $(success,$(srctree)/scripts/rust_is_available.sh) help diff --git a/scripts/rustc-version.sh b/scripts/rustc-version.sh new file mode 100755 index 000000000000..4e22593e2eab --- /dev/null +++ b/scripts/rustc-version.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Usage: $ ./rustc-version.sh rustc +# +# Print the Rust compiler version in a 6 or 7-digit form. + +# Convert the version string x.y.z to a canonical up-to-7-digits form. +# +# Note that this function uses one more digit (compared to other +# instances in other version scripts) to give a bit more space to +# `rustc` since it will reach 1.100.0 in late 2026. +get_canonical_version() +{ + IFS=. + set -- $1 + echo $((100000 * $1 + 100 * $2 + $3)) +} + +if output=$("$@" --version 2>/dev/null); then + set -- $output + get_canonical_version $2 +else + echo 0 + exit 1 +fi -- cgit v1.2.3 From 5134a335cfe6ebdd2420e15b5f6c06915040aa51 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 2 Sep 2024 18:55:29 +0200 Subject: kbuild: rust: re-run Kconfig if the version text changes Re-run Kconfig if we detect the Rust compiler has changed via the version text, like it is done for C. Unlike C, and unlike `RUSTC_VERSION`, the `RUSTC_VERSION_TEXT` is kept under `depends on RUST`, since it should not be needed unless `RUST` is enabled. Reviewed-by: Nicolas Schier Tested-by: Alice Ryhl Acked-by: Masahiro Yamada Link: https://lore.kernel.org/r/20240902165535.1101978-3-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- Makefile | 8 +++++--- init/Kconfig | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'init') diff --git a/Makefile b/Makefile index 68ebd6d6b444..1883aeb919a4 100644 --- a/Makefile +++ b/Makefile @@ -648,9 +648,11 @@ endif # The expansion should be delayed until arch/$(SRCARCH)/Makefile is included. # Some architectures define CROSS_COMPILE in arch/$(SRCARCH)/Makefile. -# CC_VERSION_TEXT is referenced from Kconfig (so it needs export), -# and from include/config/auto.conf.cmd to detect the compiler upgrade. +# CC_VERSION_TEXT and RUSTC_VERSION_TEXT are referenced from Kconfig (so they +# need export), and from include/config/auto.conf.cmd to detect the compiler +# upgrade. CC_VERSION_TEXT = $(subst $(pound),,$(shell LC_ALL=C $(CC) --version 2>/dev/null | head -n 1)) +RUSTC_VERSION_TEXT = $(subst $(pound),,$(shell $(RUSTC) --version 2>/dev/null)) ifneq ($(findstring clang,$(CC_VERSION_TEXT)),) include $(srctree)/scripts/Makefile.clang @@ -671,7 +673,7 @@ ifdef config-build # KBUILD_DEFCONFIG may point out an alternative default configuration # used for 'make defconfig' include $(srctree)/arch/$(SRCARCH)/Makefile -export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT +export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT RUSTC_VERSION_TEXT config: outputmakefile scripts_basic FORCE $(Q)$(MAKE) $(build)=scripts/kconfig $@ diff --git a/init/Kconfig b/init/Kconfig index 38c1cfcce821..c6b744a48dcc 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1927,7 +1927,9 @@ config RUST config RUSTC_VERSION_TEXT string depends on RUST - default "$(shell,$(RUSTC) --version 2>/dev/null)" + default "$(RUSTC_VERSION_TEXT)" + help + See `CC_VERSION_TEXT`. config BINDGEN_VERSION_TEXT string -- cgit v1.2.3 From d077242d68a31075ef5f5da041bf8f6fc19aa231 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Thu, 29 Aug 2024 08:22:45 +0000 Subject: rust: support for shadow call stack sanitizer 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 Reviewed-by: Ard Biesheuvel Reviewed-by: Kees Cook Acked-by: Will Deacon Signed-off-by: Alice Ryhl 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 --- Makefile | 1 + arch/arm64/Kconfig | 14 +++++++++++++- arch/arm64/Makefile | 3 +++ arch/riscv/Kconfig | 9 ++++++++- init/Kconfig | 1 - 5 files changed, 25 insertions(+), 3 deletions(-) (limited to 'init') diff --git a/Makefile b/Makefile index 1883aeb919a4..ec9cec3b650d 100644 --- 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 diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a2f8ff354ca6..d56400bfd20a 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -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 diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index f6bc3da1ef11..b058c4803efb 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/arch/riscv/Kconfig b/arch/riscv/Kconfig index 0f3cd7c3a436..6d9234216c69 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -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 diff --git a/init/Kconfig b/init/Kconfig index c6b744a48dcc..9bcda3b0a20f 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -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. -- cgit v1.2.3 From ca627e636551e74b528f150d744f67d9a63f0ae7 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Thu, 12 Sep 2024 21:00:44 +0200 Subject: rust: cfi: add support for CFI_CLANG with Rust Make it possible to use the Control Flow Integrity (CFI) sanitizer when Rust is enabled. Enabling CFI with Rust requires that CFI is configured to normalize integer types so that all integer types of the same size and signedness are compatible under CFI. Rust and C use the same LLVM backend for code generation, so Rust KCFI is compatible with the KCFI used in the kernel for C. In the case of FineIBT, CFI also depends on -Zpatchable-function-entry for rewriting the function prologue, so we set that flag for Rust as well. The flag for FineIBT requires rustc 1.80.0 or later, so include a Kconfig requirement for that. Enabling Rust will select CFI_ICALL_NORMALIZE_INTEGERS because the flag is required to use Rust with CFI. Using select rather than `depends on` avoids the case where Rust is not visible in menuconfig due to CFI_ICALL_NORMALIZE_INTEGERS not being enabled. One disadvantage of select is that RUST must `depends on` all of the things that CFI_ICALL_NORMALIZE_INTEGERS depends on to avoid invalid configurations. Alice has been using KCFI on her phone for several months, so it is reasonably well tested on arm64. Signed-off-by: Matthew Maurer Co-developed-by: Alice Ryhl Signed-off-by: Alice Ryhl Reviewed-by: Sami Tolvanen Tested-by: Gatlin Newhouse Acked-by: Kees Cook Acked-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/r/20240801-kcfi-v2-2-c93caed3d121@google.com [ Replaced `!FINEIBT` requirement with `!CALL_PADDING` to prevent a build error on older Rust compilers. Fixed typo. - Miguel ] Signed-off-by: Miguel Ojeda --- Makefile | 7 +++++++ arch/x86/Makefile | 4 ++++ init/Kconfig | 4 +++- rust/Makefile | 2 +- scripts/generate_rust_target.rs | 1 + 5 files changed, 16 insertions(+), 2 deletions(-) (limited to 'init') diff --git a/Makefile b/Makefile index 35253bff5ca2..08ba14ef128e 100644 --- a/Makefile +++ b/Makefile @@ -957,6 +957,13 @@ CC_FLAGS_CFI := -fsanitize=kcfi ifdef CONFIG_CFI_ICALL_NORMALIZE_INTEGERS CC_FLAGS_CFI += -fsanitize-cfi-icall-experimental-normalize-integers endif +ifdef CONFIG_RUST + # Always pass -Zsanitizer-cfi-normalize-integers as CONFIG_RUST selects + # CONFIG_CFI_ICALL_NORMALIZE_INTEGERS. + RUSTC_FLAGS_CFI := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers + KBUILD_RUSTFLAGS += $(RUSTC_FLAGS_CFI) + export RUSTC_FLAGS_CFI +endif KBUILD_CFLAGS += $(CC_FLAGS_CFI) export CC_FLAGS_CFI endif diff --git a/arch/x86/Makefile b/arch/x86/Makefile index a1883a30a5d8..cd75e78a06c1 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -242,6 +242,10 @@ ifdef CONFIG_CALL_PADDING PADDING_CFLAGS := -fpatchable-function-entry=$(CONFIG_FUNCTION_PADDING_BYTES),$(CONFIG_FUNCTION_PADDING_BYTES) KBUILD_CFLAGS += $(PADDING_CFLAGS) export PADDING_CFLAGS + +PADDING_RUSTFLAGS := -Zpatchable-function-entry=$(CONFIG_FUNCTION_PADDING_BYTES),$(CONFIG_FUNCTION_PADDING_BYTES) +KBUILD_RUSTFLAGS += $(PADDING_RUSTFLAGS) +export PADDING_RUSTFLAGS endif KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE) diff --git a/init/Kconfig b/init/Kconfig index 9bcda3b0a20f..53f4589b7847 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1905,11 +1905,13 @@ config RUST bool "Rust support" depends on HAVE_RUST depends on RUST_IS_AVAILABLE - depends on !CFI_CLANG depends on !MODVERSIONS depends on !GCC_PLUGIN_RANDSTRUCT depends on !RANDSTRUCT depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE + depends on !CFI_CLANG || RUSTC_VERSION >= 107900 && $(cc-option,-fsanitize=kcfi -fsanitize-cfi-icall-experimental-normalize-integers) + select CFI_ICALL_NORMALIZE_INTEGERS if CFI_CLANG + depends on !CALL_PADDING || RUSTC_VERSION >= 108000 help Enables Rust support in the kernel. diff --git a/rust/Makefile b/rust/Makefile index 4eae318f36ff..dd76dc27d666 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -306,7 +306,7 @@ $(obj)/bindings/bindings_helpers_generated.rs: $(src)/helpers/helpers.c FORCE quiet_cmd_exports = EXPORTS $@ cmd_exports = \ $(NM) -p --defined-only $< \ - | awk '/ (T|R|D) / {printf "EXPORT_SYMBOL_RUST_GPL(%s);\n",$$3}' > $@ + | awk '$$2~/(T|R|D)/ && $$3!~/__cfi/ {printf "EXPORT_SYMBOL_RUST_GPL(%s);\n",$$3}' > $@ $(obj)/exports_core_generated.h: $(obj)/core.o FORCE $(call if_changed,exports) diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs index fbf723996d20..087c1d13d33b 100644 --- a/scripts/generate_rust_target.rs +++ b/scripts/generate_rust_target.rs @@ -207,6 +207,7 @@ fn main() { } ts.push("features", features); ts.push("llvm-target", "x86_64-linux-gnu"); + ts.push("supported-sanitizers", ["kcfi"]); ts.push("target-pointer-width", "64"); } else if cfg.has("X86_32") { // This only works on UML, as i386 otherwise needs regparm support in rustc -- cgit v1.2.3 From f64e2f3a66e30319023b7924d438d159ac742d63 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 20 Aug 2024 19:48:57 +0000 Subject: rust: kasan: Rust does not support KHWASAN Rust does not yet have support for software tags. Prevent RUST from being selected if KASAN_SW_TAGS is enabled. Signed-off-by: Matthew Maurer Reviewed-by: Andrey Konovalov Link: https://lore.kernel.org/r/20240820194910.187826-3-mmaurer@google.com Signed-off-by: Miguel Ojeda --- init/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'init') diff --git a/init/Kconfig b/init/Kconfig index 53f4589b7847..4ea2a161d362 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1912,6 +1912,7 @@ config RUST depends on !CFI_CLANG || RUSTC_VERSION >= 107900 && $(cc-option,-fsanitize=kcfi -fsanitize-cfi-icall-experimental-normalize-integers) select CFI_ICALL_NORMALIZE_INTEGERS if CFI_CLANG depends on !CALL_PADDING || RUSTC_VERSION >= 108000 + depends on !KASAN_SW_TAGS help Enables Rust support in the kernel. -- cgit v1.2.3