On Mon, Oct 12, 2026 at 01:39:14PM +0000, Marco Elver wrote: > Rust supports ThreadSanitizer instrumentation via LLVM, which is what > KCSAN relies on; however, Rust code is not currently instrumented. > > Pass -Zsanitizer=thread and the same TSan backend options used for C > code to rustc. Wire up KCSAN_SANITIZE in scripts/Makefile.lib for parity > with C (though rustc currently rejects linking crates with mismatched > instrumentation). > > rustc only accepts -Zsanitizer=thread for targets that declare support > for it. Of the targets used by the kernel, this is only possible for the > generated x86_64 target specification, so restrict instrumentation of > Rust code to x86_64 for now via HAVE_KCSAN_RUSTC. On other architectures > Rust code remains uninstrumented as before. > > All TSan options used are supported by the LLVM versions of the minimum > supported rustc, so no rustc-option checks are needed (they would also > fail, because x86_64-unknown-none used for option checks does not > support -Zsanitizer=thread). > > With this enabled we can detect data races in kernel Rust code and > between Rust and C code. >
Help has finally arrived! :) Thank you for looking into this, for both patches: Acked-by: Boqun Feng <[email protected]> Regards, Boqun > Signed-off-by: Marco Elver <[email protected]> > --- > Documentation/dev-tools/kcsan.rst | 7 +++++++ > lib/Kconfig.kcsan | 7 +++++++ > scripts/Makefile.kcsan | 13 +++++++++++++ > scripts/Makefile.lib | 3 +++ > scripts/generate_rust_target.rs | 2 +- > 5 files changed, 31 insertions(+), 1 deletion(-) > > diff --git a/Documentation/dev-tools/kcsan.rst > b/Documentation/dev-tools/kcsan.rst > index 8575178aa87f..3bb8754f844b 100644 > --- a/Documentation/dev-tools/kcsan.rst > +++ b/Documentation/dev-tools/kcsan.rst > @@ -14,6 +14,9 @@ Usage > KCSAN is supported by both GCC and Clang. With GCC we require version 11 or > later, and with Clang also require version 11 or later. > > +Rust code is instrumented as well on architectures whose Rust target supports > +it (currently only x86_64; see ``CONFIG_HAVE_KCSAN_RUSTC``). > + > To enable KCSAN configure the kernel with:: > > CONFIG_KCSAN = y > @@ -121,6 +124,10 @@ the below options are available: > > KCSAN_SANITIZE := n > > + Note that ``rustc`` rejects linking crates built with and without KCSAN > + instrumentation, so ``KCSAN_SANITIZE`` and ``KCSAN_SANITIZE_<target>.o`` > + cannot currently be used for Rust code. > + > .. _"Marking Shared-Memory Accesses" in the LKMM: > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/memory-model/Documentation/access-marking.txt > > Furthermore, it is possible to tell KCSAN to show or hide entire classes of > diff --git a/lib/Kconfig.kcsan b/lib/Kconfig.kcsan > index 4ce4b0c0109c..f0096e1c8b61 100644 > --- a/lib/Kconfig.kcsan > +++ b/lib/Kconfig.kcsan > @@ -10,6 +10,13 @@ config HAVE_KCSAN_COMPILER > For the list of compilers that support KCSAN, please see > <file:Documentation/dev-tools/kcsan.rst>. > > +config HAVE_KCSAN_RUSTC > + def_bool RUST && X86_64 > + help > + rustc only accepts -Zsanitizer=thread for targets that declare > + support for it; of the kernel's Rust targets, only x86_64 does. > + Elsewhere, Rust code is not instrumented. > + > menuconfig KCSAN > bool "KCSAN: dynamic data race detector" > depends on HAVE_ARCH_KCSAN && HAVE_KCSAN_COMPILER > diff --git a/scripts/Makefile.kcsan b/scripts/Makefile.kcsan > index 19f693b68a96..01af6fd71006 100644 > --- a/scripts/Makefile.kcsan > +++ b/scripts/Makefile.kcsan > @@ -24,3 +24,16 @@ kcsan-cflags += $(call cc-option,$(call > cc-param,tsan-instrument-func-entry-exit > endif > > export CFLAGS_KCSAN := $(kcsan-cflags) > + > +ifdef CONFIG_HAVE_KCSAN_RUSTC > +# The minimum supported rustc's LLVM supports all of these options. > +rustc-param = -Cllvm-args=-$(1) > +kcsan-rustflags := -Zsanitizer=thread \ > + $(call rustc-param,tsan-compound-read-before-write=1) \ > + $(call rustc-param,tsan-distinguish-volatile=1) > +ifndef CONFIG_KCSAN_WEAK_MEMORY > +kcsan-rustflags += $(call rustc-param,tsan-instrument-func-entry-exit=0) > +endif > +endif > + > +export RUSTFLAGS_KCSAN := $(kcsan-rustflags) > diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib > index 0a4fdd8bd975..78f1c23e54be 100644 > --- a/scripts/Makefile.lib > +++ b/scripts/Makefile.lib > @@ -98,6 +98,9 @@ ifeq ($(CONFIG_KCSAN),y) > _c_flags += $(if $(patsubst n%,, \ > > $(KCSAN_SANITIZE_$(target-stem).o)$(KCSAN_SANITIZE)$(is-kernel-object)), \ > $(CFLAGS_KCSAN)) > +_rust_flags += $(if $(patsubst n%,, \ > + > $(KCSAN_SANITIZE_$(target-stem).o)$(KCSAN_SANITIZE)$(is-kernel-object)), \ > + $(RUSTFLAGS_KCSAN)) > # Some uninstrumented files provide implied barriers required to avoid false > # positives: set KCSAN_INSTRUMENT_BARRIERS for barrier instrumentation only. > _c_flags += $(if $(patsubst n%,, \ > diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs > index 7687b0dd5474..4b02bffa6b46 100644 > --- a/scripts/generate_rust_target.rs > +++ b/scripts/generate_rust_target.rs > @@ -231,7 +231,7 @@ fn main() { > } > ts.push("features", features); > ts.push("llvm-target", "x86_64-linux-gnu"); > - ts.push("supported-sanitizers", ["kcfi", "kernel-address"]); > + ts.push("supported-sanitizers", ["kcfi", "kernel-address", > "thread"]); > if cfg.rustc_version_atleast(1, 91, 0) { > ts.push("target-pointer-width", 64); > } else { > -- > 2.56.0.385.gd3acb90ef8-goog >

