From e4b23c7381282aec541a66b0745e06e49979867c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 21 Nov 2025 12:18:59 +0100 Subject: [PATCH] 6.6-stable patches added patches: memcg-fix-data-race-kcsan-bug-in-rstats.patch --- ...cg-fix-data-race-kcsan-bug-in-rstats.patch | 103 ++++++++++++++++++ queue-6.6/series | 1 + 2 files changed, 104 insertions(+) create mode 100644 queue-6.6/memcg-fix-data-race-kcsan-bug-in-rstats.patch diff --git a/queue-6.6/memcg-fix-data-race-kcsan-bug-in-rstats.patch b/queue-6.6/memcg-fix-data-race-kcsan-bug-in-rstats.patch new file mode 100644 index 0000000000..08995d5018 --- /dev/null +++ b/queue-6.6/memcg-fix-data-race-kcsan-bug-in-rstats.patch @@ -0,0 +1,103 @@ +From 78ec6f9df6642418411c534683da6133e0962ec7 Mon Sep 17 00:00:00 2001 +From: Breno Leitao +Date: Wed, 24 Apr 2024 05:59:39 -0700 +Subject: memcg: fix data-race KCSAN bug in rstats + +From: Breno Leitao + +commit 78ec6f9df6642418411c534683da6133e0962ec7 upstream. + +A data-race issue in memcg rstat occurs when two distinct code paths +access the same 4-byte region concurrently. KCSAN detection triggers the +following BUG as a result. + + BUG: KCSAN: data-race in __count_memcg_events / mem_cgroup_css_rstat_flush + + write to 0xffffe8ffff98e300 of 4 bytes by task 5274 on cpu 17: + mem_cgroup_css_rstat_flush (mm/memcontrol.c:5850) + cgroup_rstat_flush_locked (kernel/cgroup/rstat.c:243 (discriminator 7)) + cgroup_rstat_flush (./include/linux/spinlock.h:401 kernel/cgroup/rstat.c:278) + mem_cgroup_flush_stats.part.0 (mm/memcontrol.c:767) + memory_numa_stat_show (mm/memcontrol.c:6911) + + + read to 0xffffe8ffff98e300 of 4 bytes by task 410848 on cpu 27: + __count_memcg_events (mm/memcontrol.c:725 mm/memcontrol.c:962) + count_memcg_event_mm.part.0 (./include/linux/memcontrol.h:1097 ./include/linux/memcontrol.h:1120) + handle_mm_fault (mm/memory.c:5483 mm/memory.c:5622) + + + value changed: 0x00000029 -> 0x00000000 + +The race occurs because two code paths access the same "stats_updates" +location. Although "stats_updates" is a per-CPU variable, it is remotely +accessed by another CPU at +cgroup_rstat_flush_locked()->mem_cgroup_css_rstat_flush(), leading to the +data race mentioned. + +Considering that memcg_rstat_updated() is in the hot code path, adding a +lock to protect it may not be desirable, especially since this variable +pertains solely to statistics. + +Therefore, annotating accesses to stats_updates with READ/WRITE_ONCE() can +prevent KCSAN splats and potential partial reads/writes. + +Link: https://lkml.kernel.org/r/20240424125940.2410718-1-leitao@debian.org +Fixes: 9cee7e8ef3e3 ("mm: memcg: optimize parent iteration in memcg_rstat_updated()") +Signed-off-by: Breno Leitao +Suggested-by: Shakeel Butt +Acked-by: Johannes Weiner +Acked-by: Shakeel Butt +Reviewed-by: Yosry Ahmed +Cc: Michal Hocko +Cc: Roman Gushchin +Cc: Muchun Song +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/memcontrol.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -710,6 +710,7 @@ static inline void memcg_rstat_updated(s + { + struct memcg_vmstats_percpu *statc; + int cpu = smp_processor_id(); ++ unsigned int stats_updates; + + if (!val) + return; +@@ -717,8 +718,9 @@ static inline void memcg_rstat_updated(s + cgroup_rstat_updated(memcg->css.cgroup, cpu); + statc = this_cpu_ptr(memcg->vmstats_percpu); + for (; statc; statc = statc->parent) { +- statc->stats_updates += abs(val); +- if (statc->stats_updates < MEMCG_CHARGE_BATCH) ++ stats_updates = READ_ONCE(statc->stats_updates) + abs(val); ++ WRITE_ONCE(statc->stats_updates, stats_updates); ++ if (stats_updates < MEMCG_CHARGE_BATCH) + continue; + + /* +@@ -726,9 +728,9 @@ static inline void memcg_rstat_updated(s + * redundant. Avoid the overhead of the atomic update. + */ + if (!memcg_vmstats_needs_flush(statc->vmstats)) +- atomic64_add(statc->stats_updates, ++ atomic64_add(stats_updates, + &statc->vmstats->stats_updates); +- statc->stats_updates = 0; ++ WRITE_ONCE(statc->stats_updates, 0); + } + } + +@@ -5690,7 +5692,7 @@ static void mem_cgroup_css_rstat_flush(s + } + } + } +- statc->stats_updates = 0; ++ WRITE_ONCE(statc->stats_updates, 0); + /* We are in a per-cpu loop here, only do the atomic write once */ + if (atomic64_read(&memcg->vmstats->stats_updates)) + atomic64_set(&memcg->vmstats->stats_updates, 0); diff --git a/queue-6.6/series b/queue-6.6/series index c95a5fac44..0d5403a2ec 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -526,3 +526,4 @@ memory-tiers-use-default_dram_perf_ref_source-in-log-message.patch mm-memory-tier-fix-abstract-distance-calculation-overflow.patch mm-memcg-optimize-parent-iteration-in-memcg_rstat_updated.patch acpi-hmat-remove-register-of-memory-node-for-generic-target.patch +memcg-fix-data-race-kcsan-bug-in-rstats.patch -- 2.47.3