linux-kbuild.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH early RFC 0/4] running KASAN off of KCSAN's TSAN hooks
@ 2025-08-04 19:17 Jann Horn
  2025-08-04 19:17 ` [PATCH early RFC 1/4] kbuild: kasan,kcsan: refactor out enablement check Jann Horn
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Jann Horn @ 2025-08-04 19:17 UTC (permalink / raw)
  To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
	Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Andrew Morton, Marco Elver,
	Christoph Lameter, David Rientjes, Vlastimil Babka,
	Roman Gushchin, Harry Yoo
  Cc: linux-kbuild, linux-kernel, kasan-dev, linux-mm, Jann Horn

This is an experimental series for running KASAN off of KCSAN's TSAN
hooks, to allow the two modes to coexist.

The first two patches are cleanups that I think are worth landing
independently of the rest of the series.

Patch 3 implements running KASAN off of KCSAN hooks; patch 4 is a little
tweak to KCSAN's integration with SLUB.

To be transparent: This is part of a larger project I'm tinkering on; I
figured I'd send this part early since it could reasonably be useful as
a standalone feature, but my real usecase involves plumbing the data
from KCSAN further into other stuff like KCOV, and my code for that
is still very much work in progress.
If you think this feature isn't worth merging by itself, I think that'd
also be reasonable; in that case I would appreciate a very short reply
on whether this is something you'd consider merging as part of a larger
feature, or if you strongly dislike what I'm doing here.

The reason why I decided to go with running KASAN off KCSAN
instrumentation, not the other way around, is that TSAN hooks provide
more information about memory ordering properties than ASAN hooks do.

An alternate approach might be to merge ASAN and TSAN in the compiler
into one combined memory access instrumentation feature; but I don't
think my weird usecase warrants significant compiler changes at this
point.

I have checked that the KASAN unit tests (other than the ones I
explicitly disabled in my patch, and also excluding the two that are
currently failing in mainline) pass with CONFIG_KASAN_KCSAN.

The current version of this series applies on top of Linux 6.16.

Signed-off-by: Jann Horn <jannh@google.com>
---
Jann Horn (4):
      kbuild: kasan,kcsan: refactor out enablement check
      kbuild: kasan: refactor open coded cflags for kasan test
      kasan: add support for running via KCSAN hooks
      mm/slub: Defer KCSAN hook on free to KASAN if available

 include/linux/kasan.h   | 14 ++++++++++++++
 kernel/kcsan/core.c     | 13 +++++++++++++
 lib/Kconfig.kasan       | 17 +++++++++++++++++
 lib/Kconfig.kcsan       |  2 +-
 mm/kasan/Makefile       | 12 ++----------
 mm/kasan/common.c       |  5 +++++
 mm/kasan/kasan.h        | 11 -----------
 mm/kasan/kasan_test_c.c |  4 ++++
 mm/kasan/shadow.c       |  3 ++-
 mm/slub.c               |  9 +++++++--
 scripts/Makefile.lib    | 20 +++++++++++---------
 11 files changed, 76 insertions(+), 34 deletions(-)
---
base-commit: 038d61fd642278bab63ee8ef722c50d10ab01e8f
change-id: 20250728-kasan-via-kcsan-e5ad0552edbb

-- 
Jann Horn <jannh@google.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH early RFC 1/4] kbuild: kasan,kcsan: refactor out enablement check
  2025-08-04 19:17 [PATCH early RFC 0/4] running KASAN off of KCSAN's TSAN hooks Jann Horn
@ 2025-08-04 19:17 ` Jann Horn
  2025-08-04 19:17 ` [PATCH early RFC 2/4] kbuild: kasan: refactor open coded cflags for kasan test Jann Horn
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Jann Horn @ 2025-08-04 19:17 UTC (permalink / raw)
  To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
	Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Andrew Morton, Marco Elver,
	Christoph Lameter, David Rientjes, Vlastimil Babka,
	Roman Gushchin, Harry Yoo
  Cc: linux-kbuild, linux-kernel, kasan-dev, linux-mm, Jann Horn

In preparation for making the logic for enabling KASAN/KCSAN compiler
instrumentation more complicated, refactor the existing logic to be more
readable and (for KASAN) less repetitive.

Signed-off-by: Jann Horn <jannh@google.com>
---
 scripts/Makefile.lib | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 1d581ba5df66..017c9801b6bb 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -52,14 +52,12 @@ endif
 # Enable address sanitizer flags for kernel except some files or directories
 # we don't want to check (depends on variables KASAN_SANITIZE_obj.o, KASAN_SANITIZE)
 #
+is-kasan-compatible = $(patsubst n%,, \
+	$(KASAN_SANITIZE_$(target-stem).o)$(KASAN_SANITIZE)$(is-kernel-object))
 ifeq ($(CONFIG_KASAN),y)
 ifneq ($(CONFIG_KASAN_HW_TAGS),y)
-_c_flags += $(if $(patsubst n%,, \
-		$(KASAN_SANITIZE_$(target-stem).o)$(KASAN_SANITIZE)$(is-kernel-object)), \
-		$(CFLAGS_KASAN), $(CFLAGS_KASAN_NOSANITIZE))
-_rust_flags += $(if $(patsubst n%,, \
-		$(KASAN_SANITIZE_$(target-stem).o)$(KASAN_SANITIZE)$(is-kernel-object)), \
-		$(RUSTFLAGS_KASAN))
+_c_flags += $(if $(is-kasan-compatible), $(CFLAGS_KASAN), $(CFLAGS_KASAN_NOSANITIZE))
+_rust_flags += $(if $(is-kasan-compatible), $(RUSTFLAGS_KASAN))
 endif
 endif
 
@@ -94,10 +92,10 @@ endif
 # Enable KCSAN flags except some files or directories we don't want to check
 # (depends on variables KCSAN_SANITIZE_obj.o, KCSAN_SANITIZE)
 #
+is-kcsan-compatible = $(patsubst n%,, \
+	$(KCSAN_SANITIZE_$(target-stem).o)$(KCSAN_SANITIZE)$(is-kernel-object))
 ifeq ($(CONFIG_KCSAN),y)
-_c_flags += $(if $(patsubst n%,, \
-	$(KCSAN_SANITIZE_$(target-stem).o)$(KCSAN_SANITIZE)$(is-kernel-object)), \
-	$(CFLAGS_KCSAN))
+_c_flags += $(if $(is-kcsan-compatible), $(CFLAGS_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%,, \

-- 
2.50.1.565.gc32cd1483b-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH early RFC 2/4] kbuild: kasan: refactor open coded cflags for kasan test
  2025-08-04 19:17 [PATCH early RFC 0/4] running KASAN off of KCSAN's TSAN hooks Jann Horn
  2025-08-04 19:17 ` [PATCH early RFC 1/4] kbuild: kasan,kcsan: refactor out enablement check Jann Horn
@ 2025-08-04 19:17 ` Jann Horn
  2025-08-05 12:30   ` Marco Elver
  2025-08-04 19:17 ` [PATCH early RFC 3/4] kasan: add support for running via KCSAN hooks Jann Horn
  2025-08-04 19:17 ` [PATCH early RFC 4/4] mm/slub: Defer KCSAN hook on free to KASAN if available Jann Horn
  3 siblings, 1 reply; 7+ messages in thread
From: Jann Horn @ 2025-08-04 19:17 UTC (permalink / raw)
  To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
	Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Andrew Morton, Marco Elver,
	Christoph Lameter, David Rientjes, Vlastimil Babka,
	Roman Gushchin, Harry Yoo
  Cc: linux-kbuild, linux-kernel, kasan-dev, linux-mm, Jann Horn

In the Makefile for mm/kasan/, KASAN is broadly disabled to prevent the
KASAN runtime from recursing into itself; but the KASAN tests must be
exempt from that.

This is currently implemented by duplicating the same logic that is also
in scripts/Makefile.lib. In preparation for changing that logic,
refactor away the duplicate logic - we already have infrastructure for
opting in specific files inside directories that are opted out.

Signed-off-by: Jann Horn <jannh@google.com>
---
 mm/kasan/Makefile | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/mm/kasan/Makefile b/mm/kasan/Makefile
index dd93ae8a6beb..922b2e6f6d14 100644
--- a/mm/kasan/Makefile
+++ b/mm/kasan/Makefile
@@ -35,18 +35,10 @@ CFLAGS_shadow.o := $(CC_FLAGS_KASAN_RUNTIME)
 CFLAGS_hw_tags.o := $(CC_FLAGS_KASAN_RUNTIME)
 CFLAGS_sw_tags.o := $(CC_FLAGS_KASAN_RUNTIME)
 
-CFLAGS_KASAN_TEST := $(CFLAGS_KASAN)
-ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
-# If compiler instruments memintrinsics by prefixing them with __asan/__hwasan,
-# we need to treat them normally (as builtins), otherwise the compiler won't
-# recognize them as instrumentable. If it doesn't instrument them, we need to
-# pass -fno-builtin, so the compiler doesn't inline them.
-CFLAGS_KASAN_TEST += -fno-builtin
-endif
+KASAN_SANITIZE_kasan_test_c.o := y
+KASAN_SANITIZE_kasan_test_rust.o := y
 
 CFLAGS_REMOVE_kasan_test_c.o += $(call cc-option, -Wvla-larger-than=1)
-CFLAGS_kasan_test_c.o := $(CFLAGS_KASAN_TEST)
-RUSTFLAGS_kasan_test_rust.o := $(RUSTFLAGS_KASAN)
 
 obj-y := common.o report.o
 obj-$(CONFIG_KASAN_GENERIC) += init.o generic.o report_generic.o shadow.o quarantine.o

-- 
2.50.1.565.gc32cd1483b-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH early RFC 3/4] kasan: add support for running via KCSAN hooks
  2025-08-04 19:17 [PATCH early RFC 0/4] running KASAN off of KCSAN's TSAN hooks Jann Horn
  2025-08-04 19:17 ` [PATCH early RFC 1/4] kbuild: kasan,kcsan: refactor out enablement check Jann Horn
  2025-08-04 19:17 ` [PATCH early RFC 2/4] kbuild: kasan: refactor open coded cflags for kasan test Jann Horn
@ 2025-08-04 19:17 ` Jann Horn
  2025-08-04 19:17 ` [PATCH early RFC 4/4] mm/slub: Defer KCSAN hook on free to KASAN if available Jann Horn
  3 siblings, 0 replies; 7+ messages in thread
From: Jann Horn @ 2025-08-04 19:17 UTC (permalink / raw)
  To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
	Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Andrew Morton, Marco Elver,
	Christoph Lameter, David Rientjes, Vlastimil Babka,
	Roman Gushchin, Harry Yoo
  Cc: linux-kbuild, linux-kernel, kasan-dev, linux-mm, Jann Horn

Inserting ASAN and TSAN instrumentation at the same time is not
supported by gcc/clang, and so the kernel currently does not support
enabling KASAN (which uses ASAN) and KCSAN (which uses TSAN) at the same
time.
But luckily, the TSAN hooks provide a large part of what we get from ASAN
hooks; so it is possible to hook up KASAN indirectly through KCSAN.

There are some trade-offs with this - in particular:

 - Since OOB detection for stack and globals relies on ASAN-specific
   redzone creation in the compiler, it won't be available when using
   TSAN instrumentation (because the compiler thinks we only want
   instrumentation for catching UAF).
 - Unlike KASAN, KCSAN does not have instrumentation for functions like
   memcpy(), and this KASAN mode inherits this issue from KCSAN.
 - It makes it impossible to selectively disable KCSAN without also
   disabling KASAN, or the other way around. To be safe, this mode only
   enables KCSAN instrumentation in files in which both KASAN and KCSAN
   are allowed.
   (There are currently some places in the kernel that disable KASAN
   without disabling KCSAN - I think that's probably unintentional, and
   we might want to refactor that at some point such that either KASAN
   and KCSAN are enabled in the same files, or files covered by KCSAN
   are a subset of files covered by KASAN if that's somehow problematic.
   Opting out of every compiler instrumentation individually in makefiles
   seems suboptimal to me.)
 - I expect its performance to be significantly worse than normal KASAN,
   but have not tested that; performance is not really something I care
   about for my usecase.

NOTE: instrument_read() and such call both KASAN and KCSAN, so KASAN
will see duplicate accesses from instrument_read().

Signed-off-by: Jann Horn <jannh@google.com>
---
 include/linux/kasan.h   | 14 ++++++++++++++
 kernel/kcsan/core.c     | 13 +++++++++++++
 lib/Kconfig.kasan       | 17 +++++++++++++++++
 lib/Kconfig.kcsan       |  2 +-
 mm/kasan/kasan.h        | 11 -----------
 mm/kasan/kasan_test_c.c |  4 ++++
 mm/kasan/shadow.c       |  3 ++-
 scripts/Makefile.lib    |  6 +++++-
 8 files changed, 56 insertions(+), 14 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 890011071f2b..818c53707e72 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -75,6 +75,20 @@ extern void kasan_enable_current(void);
 /* Disable reporting bugs for current task */
 extern void kasan_disable_current(void);
 
+/**
+ * kasan_check_range - Check memory region, and report if invalid access.
+ * @addr: the accessed address
+ * @size: the accessed size
+ * @write: true if access is a write access
+ * @ret_ip: return address
+ * @return: true if access was valid, false if invalid
+ *
+ * This function is intended for KASAN-internal use and for integration with
+ * KCSAN.
+ */
+bool kasan_check_range(const void *addr, size_t size, bool write,
+				unsigned long ret_ip);
+
 #else /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
 
 static inline int kasan_add_zero_shadow(void *start, unsigned long size)
diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c
index 8a7baf4e332e..aaa9bf0141a8 100644
--- a/kernel/kcsan/core.c
+++ b/kernel/kcsan/core.c
@@ -728,6 +728,19 @@ check_access(const volatile void *ptr, size_t size, int type, unsigned long ip)
 	if (unlikely(size == 0))
 		return;
 
+#ifdef CONFIG_KASAN_KCSAN
+	/*
+	 * Use the KCSAN infrastructure to inform KASAN about memory accesses.
+	 * Do this only for real memory access, not for KCSAN assertions - in
+	 * particular, SLUB makes KCSAN assertions that can cross into ASAN
+	 * redzones, which would KASAN think that an OOB access occurred.
+	 */
+	if ((type & KCSAN_ACCESS_ASSERT) == 0) {
+		kasan_check_range((const void *)ptr, size,
+				  (type & (KCSAN_ACCESS_WRITE|KCSAN_ACCESS_COMPOUND)) != 0, ip);
+	}
+#endif
+
 again:
 	/*
 	 * Avoid user_access_save in fast-path: find_watchpoint is safe without
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index f82889a830fa..0ee9f2196448 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -133,6 +133,7 @@ choice
 
 config KASAN_OUTLINE
 	bool "Outline instrumentation"
+	depends on !KCSAN
 	help
 	  Makes the compiler insert function calls that check whether the memory
 	  is accessible before each memory access. Slower than KASAN_INLINE, but
@@ -141,17 +142,33 @@ config KASAN_OUTLINE
 config KASAN_INLINE
 	bool "Inline instrumentation"
 	depends on !ARCH_DISABLE_KASAN_INLINE
+	depends on !KCSAN
 	help
 	  Makes the compiler directly insert memory accessibility checks before
 	  each memory access. Faster than KASAN_OUTLINE (gives ~x2 boost for
 	  some workloads), but makes the kernel's .text size much bigger.
 
+config KASAN_KCSAN
+	bool "Piggyback on KCSAN (EXPERIMENTAL)"
+	depends on KASAN_GENERIC
+	depends on KCSAN
+	help
+	  Let KASAN piggyback on KCSAN instrumentation callbacks instead of
+	  using KASAN-specific compiler instrumentation.
+
+	  This limits coverage of KASAN and KCSAN to files that are supported by
+	  *both* KASAN and KCSAN.
+
+	  This is only useful if you want to run both the KASAN and KCSAN
+	  subsystems at the same time.
+
 endchoice
 
 config KASAN_STACK
 	bool "Stack instrumentation (unsafe)" if CC_IS_CLANG && !COMPILE_TEST
 	depends on KASAN_GENERIC || KASAN_SW_TAGS
 	depends on !ARCH_DISABLE_KASAN_INLINE
+	depends on !KASAN_KCSAN
 	default y if CC_IS_GCC
 	help
 	  Disables stack instrumentation and thus KASAN's ability to detect
diff --git a/lib/Kconfig.kcsan b/lib/Kconfig.kcsan
index 609ddfc73de5..86bf8f2da0a8 100644
--- a/lib/Kconfig.kcsan
+++ b/lib/Kconfig.kcsan
@@ -13,7 +13,7 @@ config HAVE_KCSAN_COMPILER
 menuconfig KCSAN
 	bool "KCSAN: dynamic data race detector"
 	depends on HAVE_ARCH_KCSAN && HAVE_KCSAN_COMPILER
-	depends on DEBUG_KERNEL && !KASAN
+	depends on DEBUG_KERNEL
 	select CONSTRUCTORS
 	select STACKTRACE
 	help
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 129178be5e64..ec191ff1fc83 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -335,17 +335,6 @@ static __always_inline bool addr_has_metadata(const void *addr)
 }
 #endif
 
-/**
- * kasan_check_range - Check memory region, and report if invalid access.
- * @addr: the accessed address
- * @size: the accessed size
- * @write: true if access is a write access
- * @ret_ip: return address
- * @return: true if access was valid, false if invalid
- */
-bool kasan_check_range(const void *addr, size_t size, bool write,
-				unsigned long ret_ip);
-
 #else /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
 
 static __always_inline bool addr_has_metadata(const void *addr)
diff --git a/mm/kasan/kasan_test_c.c b/mm/kasan/kasan_test_c.c
index 5f922dd38ffa..c4826c67aa33 100644
--- a/mm/kasan/kasan_test_c.c
+++ b/mm/kasan/kasan_test_c.c
@@ -154,6 +154,8 @@ static void kasan_test_exit(struct kunit *test)
 #define KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test) do {		\
 	if (IS_ENABLED(CONFIG_KASAN_HW_TAGS))				\
 		break;  /* No compiler instrumentation. */		\
+	if (IS_ENABLED(CONFIG_KASAN_KCSAN))				\
+		kunit_skip((test), "No checked mem*() with KCSAN");	\
 	if (IS_ENABLED(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX))	\
 		break;  /* Should always be instrumented! */		\
 	if (IS_ENABLED(CONFIG_GENERIC_ENTRY))				\
@@ -1453,6 +1455,7 @@ static void kasan_global_oob_right(struct kunit *test)
 
 	/* Only generic mode instruments globals. */
 	KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
+	KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_KCSAN);
 
 	KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p);
 }
@@ -1468,6 +1471,7 @@ static void kasan_global_oob_left(struct kunit *test)
 	 */
 	KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_CC_IS_CLANG);
 	KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
+	KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_KCSAN);
 	KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p);
 }
 
diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c
index d2c70cd2afb1..136be8e6c98d 100644
--- a/mm/kasan/shadow.c
+++ b/mm/kasan/shadow.c
@@ -38,7 +38,8 @@ bool __kasan_check_write(const volatile void *p, unsigned int size)
 }
 EXPORT_SYMBOL(__kasan_check_write);
 
-#if !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX) && !defined(CONFIG_GENERIC_ENTRY)
+#if !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX) && \
+		!defined(CONFIG_GENERIC_ENTRY) && !defined(CONFIG_KASAN_KCSAN)
 /*
  * CONFIG_GENERIC_ENTRY relies on compiler emitted mem*() calls to not be
  * instrumented. KASAN enabled toolchains should emit __asan_mem*() functions
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 017c9801b6bb..2572fcc0bf50 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -56,10 +56,13 @@ is-kasan-compatible = $(patsubst n%,, \
 	$(KASAN_SANITIZE_$(target-stem).o)$(KASAN_SANITIZE)$(is-kernel-object))
 ifeq ($(CONFIG_KASAN),y)
 ifneq ($(CONFIG_KASAN_HW_TAGS),y)
+# Disable ASAN instrumentation if KASAN is running off the KCSAN hooks.
+ifneq ($(CONFIG_KASAN_KCSAN),y)
 _c_flags += $(if $(is-kasan-compatible), $(CFLAGS_KASAN), $(CFLAGS_KASAN_NOSANITIZE))
 _rust_flags += $(if $(is-kasan-compatible), $(RUSTFLAGS_KASAN))
 endif
 endif
+endif
 
 ifeq ($(CONFIG_KMSAN),y)
 _c_flags += $(if $(patsubst n%,, \
@@ -95,7 +98,8 @@ endif
 is-kcsan-compatible = $(patsubst n%,, \
 	$(KCSAN_SANITIZE_$(target-stem).o)$(KCSAN_SANITIZE)$(is-kernel-object))
 ifeq ($(CONFIG_KCSAN),y)
-_c_flags += $(if $(is-kcsan-compatible), $(CFLAGS_KCSAN))
+enable-kcsan-instr = $(and $(is-kcsan-compatible), $(if $(CONFIG_KASAN_KCSAN),$(is-kasan-compatible),y))
+_c_flags += $(if $(enable-kcsan-instr), $(CFLAGS_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%,, \

-- 
2.50.1.565.gc32cd1483b-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH early RFC 4/4] mm/slub: Defer KCSAN hook on free to KASAN if available
  2025-08-04 19:17 [PATCH early RFC 0/4] running KASAN off of KCSAN's TSAN hooks Jann Horn
                   ` (2 preceding siblings ...)
  2025-08-04 19:17 ` [PATCH early RFC 3/4] kasan: add support for running via KCSAN hooks Jann Horn
@ 2025-08-04 19:17 ` Jann Horn
  3 siblings, 0 replies; 7+ messages in thread
From: Jann Horn @ 2025-08-04 19:17 UTC (permalink / raw)
  To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
	Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Andrew Morton, Marco Elver,
	Christoph Lameter, David Rientjes, Vlastimil Babka,
	Roman Gushchin, Harry Yoo
  Cc: linux-kbuild, linux-kernel, kasan-dev, linux-mm, Jann Horn

SLUB calls __kcsan_check_access() in slab_free_hook() so that KCSAN has
an opportunity to detect racy use-after-free bugs, for example by
delaying the freeing a bit and watching for any other accesses to the
allocation.

When KASAN and KCSAN are active at the same time, and such a racy
use-after-free occurs that KCSAN can detect, it would be nice to also
get a full KASAN report. To make that possible, move the KCSAN hook
invocation after the point where KASAN has marked the object as freed in
KASAN builds.

Signed-off-by: Jann Horn <jannh@google.com>
---
 mm/kasan/common.c | 5 +++++
 mm/slub.c         | 9 +++++++--
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index ed4873e18c75..3492a6db191e 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -263,6 +263,11 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object, bool init,
 
 	poison_slab_object(cache, object, init, still_accessible);
 
+	if (!still_accessible) {
+		__kcsan_check_access(object, cache->object_size,
+				     KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ASSERT);
+	}
+
 	/*
 	 * If the object is put into quarantine, do not let slab put the object
 	 * onto the freelist for now. The object's metadata is kept until the
diff --git a/mm/slub.c b/mm/slub.c
index 31e11ef256f9..144399aebdc6 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2311,8 +2311,13 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
 	if (!(s->flags & SLAB_DEBUG_OBJECTS))
 		debug_check_no_obj_freed(x, s->object_size);
 
-	/* Use KCSAN to help debug racy use-after-free. */
-	if (!still_accessible)
+	/*
+	 * Use KCSAN to help debug racy use-after-free.
+	 * If KASAN is also enabled, this is instead done from KASAN when the
+	 * object has already been marked as free, so that KCSAN's race-window
+	 * widening can trigger a KASAN splat.
+	 */
+	if (!IS_ENABLED(CONFIG_KASAN) && !still_accessible)
 		__kcsan_check_access(x, s->object_size,
 				     KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ASSERT);
 

-- 
2.50.1.565.gc32cd1483b-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH early RFC 2/4] kbuild: kasan: refactor open coded cflags for kasan test
  2025-08-04 19:17 ` [PATCH early RFC 2/4] kbuild: kasan: refactor open coded cflags for kasan test Jann Horn
@ 2025-08-05 12:30   ` Marco Elver
  2025-08-05 13:49     ` Jann Horn
  0 siblings, 1 reply; 7+ messages in thread
From: Marco Elver @ 2025-08-05 12:30 UTC (permalink / raw)
  To: Jann Horn
  Cc: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
	Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Andrew Morton,
	Christoph Lameter, David Rientjes, Vlastimil Babka,
	Roman Gushchin, Harry Yoo, linux-kbuild, linux-kernel, kasan-dev,
	linux-mm

On Mon, 4 Aug 2025 at 21:18, Jann Horn <jannh@google.com> wrote:
>
> In the Makefile for mm/kasan/, KASAN is broadly disabled to prevent the
> KASAN runtime from recursing into itself; but the KASAN tests must be
> exempt from that.
>
> This is currently implemented by duplicating the same logic that is also
> in scripts/Makefile.lib. In preparation for changing that logic,
> refactor away the duplicate logic - we already have infrastructure for
> opting in specific files inside directories that are opted out.
>
> Signed-off-by: Jann Horn <jannh@google.com>
> ---
>  mm/kasan/Makefile | 12 ++----------
>  1 file changed, 2 insertions(+), 10 deletions(-)
>
> diff --git a/mm/kasan/Makefile b/mm/kasan/Makefile
> index dd93ae8a6beb..922b2e6f6d14 100644
> --- a/mm/kasan/Makefile
> +++ b/mm/kasan/Makefile
> @@ -35,18 +35,10 @@ CFLAGS_shadow.o := $(CC_FLAGS_KASAN_RUNTIME)
>  CFLAGS_hw_tags.o := $(CC_FLAGS_KASAN_RUNTIME)
>  CFLAGS_sw_tags.o := $(CC_FLAGS_KASAN_RUNTIME)
>
> -CFLAGS_KASAN_TEST := $(CFLAGS_KASAN)
> -ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
> -# If compiler instruments memintrinsics by prefixing them with __asan/__hwasan,
> -# we need to treat them normally (as builtins), otherwise the compiler won't
> -# recognize them as instrumentable. If it doesn't instrument them, we need to
> -# pass -fno-builtin, so the compiler doesn't inline them.
> -CFLAGS_KASAN_TEST += -fno-builtin

Has the -fno-builtin passed to test if
!CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX become redundant?


> -endif
> +KASAN_SANITIZE_kasan_test_c.o := y
> +KASAN_SANITIZE_kasan_test_rust.o := y
>
>  CFLAGS_REMOVE_kasan_test_c.o += $(call cc-option, -Wvla-larger-than=1)
> -CFLAGS_kasan_test_c.o := $(CFLAGS_KASAN_TEST)
> -RUSTFLAGS_kasan_test_rust.o := $(RUSTFLAGS_KASAN)
>
>  obj-y := common.o report.o
>  obj-$(CONFIG_KASAN_GENERIC) += init.o generic.o report_generic.o shadow.o quarantine.o
>
> --
> 2.50.1.565.gc32cd1483b-goog
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH early RFC 2/4] kbuild: kasan: refactor open coded cflags for kasan test
  2025-08-05 12:30   ` Marco Elver
@ 2025-08-05 13:49     ` Jann Horn
  0 siblings, 0 replies; 7+ messages in thread
From: Jann Horn @ 2025-08-05 13:49 UTC (permalink / raw)
  To: Marco Elver
  Cc: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
	Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Andrew Morton,
	Christoph Lameter, David Rientjes, Vlastimil Babka,
	Roman Gushchin, Harry Yoo, linux-kbuild, linux-kernel, kasan-dev,
	linux-mm

On Tue, Aug 5, 2025 at 2:31 PM Marco Elver <elver@google.com> wrote:
> On Mon, 4 Aug 2025 at 21:18, Jann Horn <jannh@google.com> wrote:
> > In the Makefile for mm/kasan/, KASAN is broadly disabled to prevent the
> > KASAN runtime from recursing into itself; but the KASAN tests must be
> > exempt from that.
> >
> > This is currently implemented by duplicating the same logic that is also
> > in scripts/Makefile.lib. In preparation for changing that logic,
> > refactor away the duplicate logic - we already have infrastructure for
> > opting in specific files inside directories that are opted out.
> >
> > Signed-off-by: Jann Horn <jannh@google.com>
> > ---
> >  mm/kasan/Makefile | 12 ++----------
> >  1 file changed, 2 insertions(+), 10 deletions(-)
> >
> > diff --git a/mm/kasan/Makefile b/mm/kasan/Makefile
> > index dd93ae8a6beb..922b2e6f6d14 100644
> > --- a/mm/kasan/Makefile
> > +++ b/mm/kasan/Makefile
> > @@ -35,18 +35,10 @@ CFLAGS_shadow.o := $(CC_FLAGS_KASAN_RUNTIME)
> >  CFLAGS_hw_tags.o := $(CC_FLAGS_KASAN_RUNTIME)
> >  CFLAGS_sw_tags.o := $(CC_FLAGS_KASAN_RUNTIME)
> >
> > -CFLAGS_KASAN_TEST := $(CFLAGS_KASAN)
> > -ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
> > -# If compiler instruments memintrinsics by prefixing them with __asan/__hwasan,
> > -# we need to treat them normally (as builtins), otherwise the compiler won't
> > -# recognize them as instrumentable. If it doesn't instrument them, we need to
> > -# pass -fno-builtin, so the compiler doesn't inline them.
> > -CFLAGS_KASAN_TEST += -fno-builtin
>
> Has the -fno-builtin passed to test if
> !CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX become redundant?

... oh, bleh, good catch. Somehow I had convinced myself that
scripts/Makefile.kasan did this, but no, that only sets -fno-builtin
for uninstrumented code... I misunderstood what was going on here.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-08-05 13:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-04 19:17 [PATCH early RFC 0/4] running KASAN off of KCSAN's TSAN hooks Jann Horn
2025-08-04 19:17 ` [PATCH early RFC 1/4] kbuild: kasan,kcsan: refactor out enablement check Jann Horn
2025-08-04 19:17 ` [PATCH early RFC 2/4] kbuild: kasan: refactor open coded cflags for kasan test Jann Horn
2025-08-05 12:30   ` Marco Elver
2025-08-05 13:49     ` Jann Horn
2025-08-04 19:17 ` [PATCH early RFC 3/4] kasan: add support for running via KCSAN hooks Jann Horn
2025-08-04 19:17 ` [PATCH early RFC 4/4] mm/slub: Defer KCSAN hook on free to KASAN if available Jann Horn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).