diff mbox series

[2/2] rust: cfi: add support for CFI_CLANG with Rust

Message ID 20240730-kcfi-v1-2-bbb948752a30@google.com (mailing list archive)
State New
Headers show
Series Rust KCFI support | expand

Commit Message

Alice Ryhl July 30, 2024, 9:40 a.m. UTC
From: Matthew Maurer <mmaurer@google.com>

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.

Signed-off-by: Matthew Maurer <mmaurer@google.com>
Co-developed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
 Makefile                        | 7 +++++++
 init/Kconfig                    | 2 +-
 rust/Makefile                   | 2 +-
 scripts/generate_rust_target.rs | 1 +
 4 files changed, 10 insertions(+), 2 deletions(-)

Comments

Peter Zijlstra July 30, 2024, 10:32 a.m. UTC | #1
On Tue, Jul 30, 2024 at 09:40:12AM +0000, Alice Ryhl wrote:
> From: Matthew Maurer <mmaurer@google.com>
> 
> 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.

I am assuming -- because I have to, because you're not actually saying
anyting -- that this is fully compatible with the C version and all the
fun and games we play with rewriting the function prologue for FineIBT
and the like also work?

> Signed-off-by: Matthew Maurer <mmaurer@google.com>
> Co-developed-by: Alice Ryhl <aliceryhl@google.com>
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
>  Makefile                        | 7 +++++++
>  init/Kconfig                    | 2 +-
>  rust/Makefile                   | 2 +-
>  scripts/generate_rust_target.rs | 1 +
>  4 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/Makefile b/Makefile
> index 484c6900337e..8d7d52f57c63 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -955,6 +955,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 depends
> +	# on CONFIG_CFI_ICALL_NORMALIZE_INTEGERS.
> +	RS_FLAGS_CFI   := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
> +	KBUILD_RUSTFLAGS += $(RS_FLAGS_CFI)
> +	export RS_FLAGS_CFI
> +endif
>  KBUILD_CFLAGS	+= $(CC_FLAGS_CFI)
>  export CC_FLAGS_CFI
>  endif
> diff --git a/init/Kconfig b/init/Kconfig
> index b0238c4b6e79..d0d3442d1756 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1905,11 +1905,11 @@ config RUST
>  	bool "Rust support"
>  	depends on HAVE_RUST
>  	depends on RUST_IS_AVAILABLE
> -	depends on !CFI_CLANG
>  	depends on !MODVERSIONS
>  	depends on !GCC_PLUGINS
>  	depends on !RANDSTRUCT
>  	depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
> +	depends on !CFI_CLANG || RUSTC_VERSION >= 107900 && CFI_ICALL_NORMALIZE_INTEGERS
>  	help
>  	  Enables Rust support in the kernel.
>  
> diff --git a/rust/Makefile b/rust/Makefile
> index f6b9bb946609..a2c9a3e03a23 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -305,7 +305,7 @@ $(obj)/bindings/bindings_helpers_generated.rs: $(src)/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 c31657380bf9..9b184099278a 100644
> --- a/scripts/generate_rust_target.rs
> +++ b/scripts/generate_rust_target.rs
> @@ -192,6 +192,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
> 
> -- 
> 2.46.0.rc1.232.g9752f9e123-goog
>
Miguel Ojeda July 30, 2024, 11:50 a.m. UTC | #2
On Tue, Jul 30, 2024 at 11:40 AM Alice Ryhl <aliceryhl@google.com> wrote:
>
> +       RS_FLAGS_CFI   := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers

Before I forget: this should probably be `RUSTC_...` for consistency
with the rest (and, in this case, these are flags, so it makes sense
they target the particular compiler).

Cheers,
Miguel
Sami Tolvanen July 30, 2024, 3:24 p.m. UTC | #3
On Tue, Jul 30, 2024 at 3:32 AM Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Tue, Jul 30, 2024 at 09:40:12AM +0000, Alice Ryhl wrote:
> > From: Matthew Maurer <mmaurer@google.com>
> >
> > 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.
>
> I am assuming -- because I have to, because you're not actually saying
> anyting -- that this is fully compatible with the C version and all the
> fun and games we play with rewriting the function prologue for FineIBT
> and the like also work?

Rust uses the same LLVM backend for the actual code generation, so it
should be fully compatible.

Sami
Peter Zijlstra July 30, 2024, 4:03 p.m. UTC | #4
On Tue, Jul 30, 2024 at 08:24:15AM -0700, Sami Tolvanen wrote:
> On Tue, Jul 30, 2024 at 3:32 AM Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > On Tue, Jul 30, 2024 at 09:40:12AM +0000, Alice Ryhl wrote:
> > > From: Matthew Maurer <mmaurer@google.com>
> > >
> > > 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.
> >
> > I am assuming -- because I have to, because you're not actually saying
> > anyting -- that this is fully compatible with the C version and all the
> > fun and games we play with rewriting the function prologue for FineIBT
> > and the like also work?
> 
> Rust uses the same LLVM backend for the actual code generation, so it
> should be fully compatible.

Yes, but we also combine that with -fpatchable-function-entry= for a
very specific effect, and I don't think I see the Rust thingy do that.
Alice Ryhl July 30, 2024, 4:26 p.m. UTC | #5
On Tue, Jul 30, 2024 at 6:03 PM Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Tue, Jul 30, 2024 at 08:24:15AM -0700, Sami Tolvanen wrote:
> > On Tue, Jul 30, 2024 at 3:32 AM Peter Zijlstra <peterz@infradead.org> wrote:
> > >
> > > On Tue, Jul 30, 2024 at 09:40:12AM +0000, Alice Ryhl wrote:
> > > > From: Matthew Maurer <mmaurer@google.com>
> > > >
> > > > 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.
> > >
> > > I am assuming -- because I have to, because you're not actually saying
> > > anyting -- that this is fully compatible with the C version and all the
> > > fun and games we play with rewriting the function prologue for FineIBT
> > > and the like also work?
> >
> > Rust uses the same LLVM backend for the actual code generation, so it
> > should be fully compatible.
>
> Yes, but we also combine that with -fpatchable-function-entry= for a
> very specific effect, and I don't think I see the Rust thingy do that.

Oh, you're right. I missed this because we're not using FineIBT, and
when this patch was originally written we had not yet implemented a
Rust equivalent to -fpatchable-function-entry=. However, that flag is
now available as of rustc version 1.80.0, so it shouldn't be an issue.
I'll fix this for v2 of this series.

Thanks for catching this!

As for whether it works other than that, I've been using this on my
personal phone together with Rust Binder for several months, so it's
well tested on arm64.

Alice
Alice Ryhl July 30, 2024, 4:44 p.m. UTC | #6
On Tue, Jul 30, 2024 at 1:51 PM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> On Tue, Jul 30, 2024 at 11:40 AM Alice Ryhl <aliceryhl@google.com> wrote:
> >
> > +       RS_FLAGS_CFI   := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
>
> Before I forget: this should probably be `RUSTC_...` for consistency
> with the rest (and, in this case, these are flags, so it makes sense
> they target the particular compiler).

Hmm. It seems like the existing variables containing rustc flags just
use RUST not RUSTC in the name?

Alice
Miguel Ojeda July 30, 2024, 5:29 p.m. UTC | #7
On Tue, Jul 30, 2024 at 6:44 PM Alice Ryhl <aliceryhl@google.com> wrote:
>
> Hmm. It seems like the existing variables containing rustc flags just
> use RUST not RUSTC in the name?

If you mean things like RUSTFLAGS, it was because the C side uses
CFLAGS, but for the equivalent of CC_FLAGS or CLANG_FLAGS, I would say
it should be RUSTC_FLAGS.

Cheers,
Miguel
diff mbox series

Patch

diff --git a/Makefile b/Makefile
index 484c6900337e..8d7d52f57c63 100644
--- a/Makefile
+++ b/Makefile
@@ -955,6 +955,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 depends
+	# on CONFIG_CFI_ICALL_NORMALIZE_INTEGERS.
+	RS_FLAGS_CFI   := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
+	KBUILD_RUSTFLAGS += $(RS_FLAGS_CFI)
+	export RS_FLAGS_CFI
+endif
 KBUILD_CFLAGS	+= $(CC_FLAGS_CFI)
 export CC_FLAGS_CFI
 endif
diff --git a/init/Kconfig b/init/Kconfig
index b0238c4b6e79..d0d3442d1756 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1905,11 +1905,11 @@  config RUST
 	bool "Rust support"
 	depends on HAVE_RUST
 	depends on RUST_IS_AVAILABLE
-	depends on !CFI_CLANG
 	depends on !MODVERSIONS
 	depends on !GCC_PLUGINS
 	depends on !RANDSTRUCT
 	depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
+	depends on !CFI_CLANG || RUSTC_VERSION >= 107900 && CFI_ICALL_NORMALIZE_INTEGERS
 	help
 	  Enables Rust support in the kernel.
 
diff --git a/rust/Makefile b/rust/Makefile
index f6b9bb946609..a2c9a3e03a23 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -305,7 +305,7 @@  $(obj)/bindings/bindings_helpers_generated.rs: $(src)/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 c31657380bf9..9b184099278a 100644
--- a/scripts/generate_rust_target.rs
+++ b/scripts/generate_rust_target.rs
@@ -192,6 +192,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