]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rust: cfi: add support for CFI_CLANG with Rust
authorMatthew Maurer <mmaurer@google.com>
Thu, 12 Sep 2024 19:00:44 +0000 (21:00 +0200)
committerMiguel Ojeda <ojeda@kernel.org>
Mon, 16 Sep 2024 15:29:58 +0000 (17:29 +0200)
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 <mmaurer@google.com>
Co-developed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Gatlin Newhouse <gatlin.newhouse@gmail.com>
Acked-by: Kees Cook <kees@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
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 <ojeda@kernel.org>
Makefile
arch/x86/Makefile
init/Kconfig
rust/Makefile
scripts/generate_rust_target.rs

index 35253bff5ca2cd8f6040177d6ecee135e3b44917..08ba14ef128e31680fcbcca7c232607c52ea8ae8 100644 (file)
--- 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
index a1883a30a5d8024cff18c02f3c35f4c64c56a5a8..cd75e78a06c1090c9c8fd51437a0a2105d05feb5 100644 (file)
@@ -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)
index 9bcda3b0a20f5cbfdda38cae8700a958483a4d5c..53f4589b78472c7f1fbd193c8a922970841bf7d6 100644 (file)
@@ -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.
 
index 4eae318f36ff7474d8c7c27c2d4beb28cfbfc4ab..dd76dc27d666716bcee61012c1a20fbe56d7c8f0 100644 (file)
@@ -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)
index fbf723996d201cc15d5496c9ae65330804b4eda5..087c1d13d33ba2019a2d6a0d5b007e4e538f976f 100644 (file)
@@ -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