summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Elver <elver@google.com>2026-07-20 18:08:22 +0200
committerMarco Elver <elver@google.com>2026-07-20 18:18:37 +0200
commita8488ecbd7ba44d65b912dfe88a73f438eba2447 (patch)
treef2ce8dc2793642e7c74cba13308b855e0b49faf6
parent1590cf0329716306e948a8fc29f1d3ee87d3989f (diff)
kcsan: avoid unintended access checking in NMIs
If a watcher deliberately disables interrupts (either by user choice, or because we're dealing with a scoped reordered access) to avoid detecting any data races in interrupts, NMIs are still able to fire. When we set up a watchpoint on a scoped reordered access, we disabled interrupts because the same CPU cannot observe reordering of its own accesses. To ensure we observe no false positives from NMIs, disable access checking for interrupt contexts as well. Fixes: 69562e4983d9 ("kcsan: Add core support for a subset of weak memory modeling") Signed-off-by: Marco Elver <elver@google.com>
-rw-r--r--kernel/kcsan/core.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c
index 8a7baf4e332e..2db82661cd60 100644
--- a/kernel/kcsan/core.c
+++ b/kernel/kcsan/core.c
@@ -585,8 +585,14 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type, unsigned
* information is lost if dirtied by KCSAN.
*/
kcsan_save_irqtrace(current);
- if (!interrupt_watcher)
+ if (!interrupt_watcher) {
local_irq_save(irq_flags);
+ /*
+ * NMIs can still fire, disable checking for all interrupt
+ * contexts.
+ */
+ raw_cpu_ptr(&kcsan_cpu_ctx)->disable_count++;
+ }
watchpoint = insert_watchpoint((unsigned long)ptr, size, is_write);
if (watchpoint == NULL) {
@@ -699,8 +705,10 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type, unsigned
atomic_long_dec(&kcsan_counters[KCSAN_COUNTER_USED_WATCHPOINTS]);
out_unlock:
- if (!interrupt_watcher)
+ if (!interrupt_watcher) {
+ raw_cpu_ptr(&kcsan_cpu_ctx)->disable_count--;
local_irq_restore(irq_flags);
+ }
kcsan_restore_irqtrace(current);
ctx->disable_scoped--;