]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mm/slab: fix a memory leak due to bootstrapping sheaves twice
authorHarry Yoo (Oracle) <harry@kernel.org>
Mon, 13 Jul 2026 14:28:49 +0000 (23:28 +0900)
committerVlastimil Babka (SUSE) <vbabka@kernel.org>
Tue, 14 Jul 2026 14:40:07 +0000 (16:40 +0200)
When kmalloc caches are aliased, multiple cache pointers reference
the same kmem_cache. As a result, iterating over kmalloc indices and
bootstrapping sheaves can bootstrap the same cache more than once and
leak memory.

Currently, this could happen when the architecture specifies
minimum alignment for slab caches that is larger than
ARCH_KMALLOC_MINALIGN.

Bootstrap sheaves only when the cache does not have them already.
Add a warning when bootstrap_cache_sheaves() is called for a cache
that already has sheaves enabled.

Fixes: 913ffd3a1bf5 ("slab: handle kmalloc sheaves bootstrap")
Cc: stable@vger.kernel.org
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Link: https://patch.msgid.link/20260713-kmalloc-no-objext-v3-1-47c7bd138de7@kernel.org
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
mm/slub.c

index 65febe957886b26cb6b64413222bef9c3bcaca4d..f9461a0c47d31b9fb59bffe36110fab8abd38be2 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -8497,6 +8497,8 @@ static void __init bootstrap_cache_sheaves(struct kmem_cache *s)
        bool failed = false;
        int node, cpu;
 
+       VM_WARN_ON_ONCE(cache_has_sheaves(s));
+
        capacity = calculate_sheaf_capacity(s, &empty_args);
 
        /* capacity can be 0 due to debugging or SLUB_TINY */
@@ -8548,8 +8550,11 @@ static void __init bootstrap_kmalloc_sheaves(void)
 
        for (type = KMALLOC_NORMAL; type <= KMALLOC_PARTITION_END; type++) {
                for (int idx = 0; idx < KMALLOC_SHIFT_HIGH + 1; idx++) {
-                       if (kmalloc_caches[type][idx])
-                               bootstrap_cache_sheaves(kmalloc_caches[type][idx]);
+                       struct kmem_cache *s = kmalloc_caches[type][idx];
+
+                       /* Do not bootstrap twice when caches are aliased */
+                       if (s && !cache_has_sheaves(s))
+                               bootstrap_cache_sheaves(s);
                }
        }
 }