linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] kasan: fix cache shrink race with CPU hotplug
@ 2026-08-08  3:14 Hui Su
  2026-08-08  7:39 ` Andrew Morton
  0 siblings, 1 reply; 4+ messages in thread
From: Hui Su @ 2026-08-08  3:14 UTC (permalink / raw)
  To: Andrey Ryabinin, Andrew Morton
  Cc: Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov,
	Vincenzo Frascino, Zqiang, kasan-dev, linux-mm, linux-kernel,
	stable, Hui Su

kasan_quarantine_remove_cache() first invokes per_cpu_remove_cache() on
all online CPUs. Each callback moves objects belonging to the cache from
cpu_quarantine to the CPU's shrink_qlist, where they can later be freed
from task context.

kmem_cache_destroy() invokes the quarantine removal path while holding
cpus_read_lock(), but kmem_cache_shrink() does not. The latter can
therefore race with CPU offlining as follows:

  kmem_cache_shrink()             CPU hotplug
  -------------------             -----------
  on_each_cpu()
    CPU1 moves objects to
    CPU1's shrink_qlist
  on_each_cpu() returns
                                  CPU1 goes offline
                                  kasan_cpu_offline()
                                    drains cpu_quarantine
                                    leaves shrink_qlist untouched
  for_each_online_cpu()
    skips CPU1

The objects left on CPU1's shrink_qlist are not returned to the slab
allocator. This may prevent kmem_cache_shrink() from releasing slabs
that would otherwise become empty. If CPU1 remains offline, a later
kmem_cache_destroy() also skips the list and can report that the cache
still contains objects.

An intermittent occurrence was observed with a virtio-9p filesystem.
The mount and umount commands both returned 0, but the kernel logged
the following during the userspace-triggered teardown:

  [  2994.380134][  T111] BUG 9p-fcall-cache-1 (Tainted: G    B              ): Objects remaining on __kmem_cache_shutdown()
  [  2994.381140][  T111] Object 0xff11000004361118 @offset=4376
  [  2994.381607][  T111] Allocated in p9_fcall_init+0x201/0x400 age=19564 cpu=1 pid=104
  [  2994.382591][  T111]  p9_fcall_init+0x201/0x400
  [  2994.382810][  T111]  p9_tag_alloc+0x12f/0x700
  [  2994.382982][  T111]  p9_client_prepare_req+0x102/0x3e0
  [  2994.383165][  T111]  p9_client_rpc+0x1ab/0xa50
  [  2994.383334][  T111]  p9_client_getattr_dotl+0xb0/0x1a0
  [  2994.383515][  T111]  v9fs_vfs_getattr_dotl+0x115/0x360
  [  2994.383719][  T111]  vfs_getattr_nosec+0x22c/0x3a0
  [  2994.383910][  T111]  vfs_statx+0xd7/0x170
  [  2994.384062][  T111]  vfs_fstatat+0x45/0x80
  [  2994.384215][  T111]  __do_sys_newfstatat+0x84/0xe0
  [  2994.384386][  T111]  do_syscall_64+0x115/0x6a0
  [  2994.384566][  T111]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
  [  2994.399720][  T111] WARNING: mm/slub.c:1244 at __kmem_cache_shutdown+0x363/0x500, CPU#0: busybox/111
  [  2994.405655][  T111] Call Trace:
  [  2994.406325][  T111]  kmem_cache_destroy+0x73/0x1b0
  [  2994.406630][  T111]  p9_client_destroy+0x271/0x3c0
  [  2994.407210][  T111]  v9fs_session_close+0x3c/0x260
  [  2994.407409][  T111]  v9fs_kill_super+0x48/0x90
  [  2994.407584][  T111]  deactivate_locked_super+0xa3/0x160
  [  2994.407778][  T111]  cleanup_mnt+0x1dd/0x3e0

Thus, a successful umount left objects in the 9p fcall cache and
prevented the cache from being destroyed cleanly.

Per-CPU shrink_qlist storage exists for every possible CPU, and each
list is protected by its own raw spinlock. Iterate over possible CPUs
so that a list populated before its CPU went offline is drained as well.

for_each_possible_cpu() can do more work than for_each_online_cpu(), but
this change only affects CONFIG_KASAN_GENERIC kernels. The extra work is
limited to cache shrink and cache destruction paths and does not affect
the normal allocation/free fast path. It adds one raw-spinlock-protected
scan of each possible CPU's shrink list. These lists are normally empty;
a non-empty list is traversed to remove objects belonging to the cache
being shrunk or destroyed.

Fixes: 07d067e4f2ce ("kasan: fix sleeping function called from invalid context on RT kernel")
Cc: stable@vger.kernel.org
Signed-off-by: Hui Su <sh_def@163.com>
---
Changes in v2:
- Document the intermittent virtio-9p slab shutdown log and user-visible effect.
- Explain the runtime cost of scanning all possible CPUs.
- No code changes.

Link to v1: https://lore.kernel.org/r/20260806121006.1642946-1-sh_def@163.com

 mm/kasan/quarantine.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
index 6958aa713c67..16f4e67beee8 100644
--- a/mm/kasan/quarantine.c
+++ b/mm/kasan/quarantine.c
@@ -355,7 +355,12 @@ void kasan_quarantine_remove_cache(struct kmem_cache *cache)
 	 */
 	on_each_cpu(per_cpu_remove_cache, cache, 1);
 
-	for_each_online_cpu(cpu) {
+	/*
+	 * A CPU can go offline after on_each_cpu() returns, leaving cache
+	 * objects on that CPU's shrink list. Scan all possible CPUs to
+	 * drain those lists.
+	 */
+	for_each_possible_cpu(cpu) {
 		sq = per_cpu_ptr(&shrink_qlist, cpu);
 		raw_spin_lock_irqsave(&sq->lock, flags);
 		qlist_move_cache(&sq->qlist, &to_free, cache);
-- 
2.43.0



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

* Re: [PATCH v2] kasan: fix cache shrink race with CPU hotplug
  2026-08-08  3:14 [PATCH v2] kasan: fix cache shrink race with CPU hotplug Hui Su
@ 2026-08-08  7:39 ` Andrew Morton
  2026-08-08  9:38   ` Hui Su
  0 siblings, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2026-08-08  7:39 UTC (permalink / raw)
  To: Hui Su
  Cc: Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
	Dmitry Vyukov, Vincenzo Frascino, Zqiang, kasan-dev, linux-mm,
	linux-kernel, stable

On Sat,  8 Aug 2026 11:14:59 +0800 Hui Su <sh_def@163.com> wrote:

> kasan_quarantine_remove_cache() first invokes per_cpu_remove_cache() on
> all online CPUs. Each callback moves objects belonging to the cache from
> cpu_quarantine to the CPU's shrink_qlist, where they can later be freed
> from task context.
> 
> kmem_cache_destroy() invokes the quarantine removal path while holding
> cpus_read_lock(), but kmem_cache_shrink() does not. The latter can
> therefore race with CPU offlining as follows:
> 
>   kmem_cache_shrink()             CPU hotplug
>   -------------------             -----------
>   on_each_cpu()
>     CPU1 moves objects to
>     CPU1's shrink_qlist
>   on_each_cpu() returns
>                                   CPU1 goes offline
>                                   kasan_cpu_offline()
>                                     drains cpu_quarantine
>                                     leaves shrink_qlist untouched
>   for_each_online_cpu()
>     skips CPU1
> 
> The objects left on CPU1's shrink_qlist are not returned to the slab
> allocator. This may prevent kmem_cache_shrink() from releasing slabs
> that would otherwise become empty. If CPU1 remains offline, a later
> kmem_cache_destroy() also skips the list and can report that the cache
> still contains objects.
> 
> An intermittent occurrence was observed with a virtio-9p filesystem.
> The mount and umount commands both returned 0, but the kernel logged
> the following during the userspace-triggered teardown:
>
> ...
>

Thanks, I'll queue this for testing while we await maintainer review.

AI review suggests that there's a pre-existing quarantine_size
accounting flaw later in this function:

	https://sashiko.dev/#/patchset/20260808031459.3032812-1-sh_def@163.com

If true, I'm surprised this hasn't yet been reported.


Also, I'd like to see a need_resched() wrapping that expensive

		/* Scanning whole quarantine can take a while. */
		raw_spin_unlock_irqrestore(&quarantine_lock, flags);
		cond_resched();
		raw_spin_lock_irqsave(&quarantine_lock, flags);




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

* Re: [PATCH v2] kasan: fix cache shrink race with CPU hotplug
  2026-08-08  7:39 ` Andrew Morton
@ 2026-08-08  9:38   ` Hui Su
  2026-08-08 16:53     ` Andrew Morton
  0 siblings, 1 reply; 4+ messages in thread
From: Hui Su @ 2026-08-08  9:38 UTC (permalink / raw)
  To: akpm
  Cc: andreyknvl, dvyukov, glider, kasan-dev, linux-kernel, linux-mm,
	qiang1.zhang, ryabinin.a.a, sh_def, stable, vincenzo.frascino

Thanks Andrew,

On Sat, Aug 08, 2026 at 12:39:21AM -0700, Andrew Morton wrote:
> AI review suggests that there's a pre-existing quarantine_size
> accounting flaw later in this function:
>
> 	https://sashiko.dev/#/patchset/20260808031459.3032812-1-sh_def@163.com
>
> If true, I'm surprised this hasn't yet been reported.

I'll take a closer look at this. If it turns out to be a real issue,
I'll send a separate patch since it's pre-existing and unrelated to the
hotplug race fix.

> Also, I'd like to see a need_resched() wrapping that expensive
>
> 		/* Scanning whole quarantine can take a while. */
> 		raw_spin_unlock_irqrestore(&quarantine_lock, flags);
> 		cond_resched();
> 		raw_spin_lock_irqsave(&quarantine_lock, flags);

Good point, that makes sense. Would you prefer that I fold this into a
v3 of this patch, or send it as a separate follow-up patch?

Thanks,
Hui



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

* Re: [PATCH v2] kasan: fix cache shrink race with CPU hotplug
  2026-08-08  9:38   ` Hui Su
@ 2026-08-08 16:53     ` Andrew Morton
  0 siblings, 0 replies; 4+ messages in thread
From: Andrew Morton @ 2026-08-08 16:53 UTC (permalink / raw)
  To: Hui Su
  Cc: andreyknvl, dvyukov, glider, kasan-dev, linux-kernel, linux-mm,
	qiang1.zhang, ryabinin.a.a, stable, vincenzo.frascino

On Sat,  8 Aug 2026 17:38:05 +0800 Hui Su <sh_def@163.com> wrote:

> Thanks Andrew,
> 
> On Sat, Aug 08, 2026 at 12:39:21AM -0700, Andrew Morton wrote:
> > AI review suggests that there's a pre-existing quarantine_size
> > accounting flaw later in this function:
> >
> > 	https://sashiko.dev/#/patchset/20260808031459.3032812-1-sh_def@163.com
> >
> > If true, I'm surprised this hasn't yet been reported.
> 
> I'll take a closer look at this. If it turns out to be a real issue,
> I'll send a separate patch since it's pre-existing and unrelated to the
> hotplug race fix.
> 
> > Also, I'd like to see a need_resched() wrapping that expensive
> >
> > 		/* Scanning whole quarantine can take a while. */
> > 		raw_spin_unlock_irqrestore(&quarantine_lock, flags);
> > 		cond_resched();
> > 		raw_spin_lock_irqsave(&quarantine_lock, flags);
> 
> Good point, that makes sense. Would you prefer that I fold this into a
> v3 of this patch, or send it as a separate follow-up patch?

Separate patches, please.  One patch per concept.


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

end of thread, other threads:[~2026-08-08 16:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-08  3:14 [PATCH v2] kasan: fix cache shrink race with CPU hotplug Hui Su
2026-08-08  7:39 ` Andrew Morton
2026-08-08  9:38   ` Hui Su
2026-08-08 16:53     ` Andrew Morton

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).