All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH slab/for-next-fixes v3 0/4] mm/slab: fix unbounded recursion in free path with memalloc profiling
@ 2026-07-13 14:28 Harry Yoo (Oracle)
  2026-07-13 14:28 ` [PATCH slab/for-next-fixes v3 1/4] mm/slab: fix a memory leak due to bootstrapping sheaves twice Harry Yoo (Oracle)
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Harry Yoo (Oracle) @ 2026-07-13 14:28 UTC (permalink / raw)
  To: Vlastimil Babka, Harry Yoo, Andrew Morton, Hao Li,
	Christoph Lameter, David Rientjes, Roman Gushchin,
	Liam R. Howlett, Suren Baghdasaryan, Hao Ge, Kees Cook,
	Pedro Falcato, Shakeel Butt, Danielle Constantino
  Cc: linux-mm, linux-kernel

This is a follow-up fix after the recent discussion [1].
See patch 4 for the detailed description on the bug.

Based on slab/for-next-fixes (af9ea231c0b45) and is available at
git.kernel.org [2].

Instead preventing cycles by bumping up the allocation size of obj_exts
arrays, it introduces a new kmalloc type called KMALLOC_NO_OBJ_EXT and
disallow formation of cycles between kmalloc types when allocating
obj_exts arrays. obj_exts arrays of normal kmalloc caches are served
from KMALLOC_NO_OBJ_EXT caches (that don't have obj_exts), and all other
obj_exts arrays are served from normal kmalloc caches.

I tried to reuse SLAB_ALLOC_NO_RECURSE to make kmalloc_slab() select
KMALLOC_NO_OBJ_EXT, but it was not great because it does not allow
sheaves for those caches. So I introduced a new slab alloc flag
SLAB_ALLOC_NO_OBJ_EXT.

To avoid huge confusion, I had to decouple "disallowing sheaves"
semantics from SLAB_NO_OBJ_EXT and introduced SLAB_NO_SHEAVES.

While this cannot be directly backported to v6.18 and v6.12 due to lack
of SLAB_ALLOC_* flags and kmalloc_flags(), I don't this will be
particularily challenging to backport it. Instead of a new slab alloc
flag, we can use __GFP_NO_OBJ_EXT to select KMALLOC_NO_OBJ_EXT as
kmalloc caches don't have sheaves in v6.18 anyway.

[1] https://lore.kernel.org/linux-mm/9a139365-28e6-4f1e-b35b-7f6091e9aa14@kernel.org

[2] https://git.kernel.org/pub/scm/linux/kernel/git/harry/linux.git/log/?h=kmalloc-no-objext-v3r1

To: Vlastimil Babka <vbabka@kernel.org>
To: Andrew Morton <akpm@linux-foundation.org>
To: Hao Li <hao.li@linux.dev>
To: Christoph Lameter <cl@gentwo.org>
To: David Rientjes <rientjes@google.com>
To: Roman Gushchin <roman.gushchin@linux.dev>
To: Suren Baghdasaryan <surenb@google.com>
To: Hao Ge <hao.ge@linux.dev>
To: Kees Cook <kees@kernel.org>
To: Pedro Falcato <pfalcato@suse.de>
To: Shakeel Butt <shakeel.butt@linux.dev>
To: Danielle Constantino <dcostantino@meta.com>
To: Liam R. Howlett <liam@infradead.org>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>

---
Changes in v3 (range-diff included at the end):
- Do not create kmalloc-no-objext-* caches unless required (Vlastimil)
- Introduce mem_alloc_profiling_permanently_disabled() in patch 3,
  to avoid creating KMALLOC_NO_OBJ_EXT caches when mem_profiling is
  permanently disabled.
- Make KMALLOC_NO_OBJ_EXT an alias for KMALLOC_NORMAL if
  CONFIG_SLAB_OBJ_EXT is not defined and avoid ifdefs (refactoring).
- Link to v2: https://lore.kernel.org/r/20260710-kmalloc-no-objext-v2-0-2709afb6a030@kernel.org

Changes in v2:
- Fix a memory leak when kmalloc caches are aliased (patch 1).
  This is included as part of this series as patch 3 makes it
  easier to trigger the leak.

- Fix a warning in MEM_ALLOC_PROFILING_DEBUG by dropping
  mark_obj_codetag_empty() for obj_exts. Sashiko raised this and
  I reproduced it and confirmed that the warnings are gone.
  https://sashiko.dev/#/patchset/20260702-kmalloc-no-objext-v1-0-167175008538%40kernel.org

- Added R-b from Vlastimil on patch 2, thanks!
- Adjusted Vlastimil's feedback on RFC v1
- Link to v1: https://lore.kernel.org/r/20260702-kmalloc-no-objext-v1-0-167175008538@kernel.org
---

$ b4 prep --compare-to v2
1:  26e19124ce7a = 1:  701534464f8e mm/slab: fix a memory leak due to bootstrapping sheaves twice
2:  a4a3a61cea59 = 2:  8c23ba4a36c9 mm/slab: decouple SLAB_NO_SHEAVES from SLAB_NO_OBJ_EXT
-:  ------------ > 3:  c285dbfbf6fb lib/alloc_tag: introduce mem_alloc_profiling_permanently_disabled()
3:  836ba88ba786 ! 4:  8d7f1e6dd334 mm/slab: prevent unbounded recursion in free path with new kmalloc type
    @@ Commit message
         never have obj_exts arrays.
     
         To achieve this, create a new kmalloc type called KMALLOC_NO_OBJ_EXT.
    -    KMALLOC_NO_OBJ_EXT caches are created when CONFIG_SLAB_OBJ_EXT is
    -    enabled, and they have SLAB_NO_OBJ_EXT flag to prevent allocation
    -    of obj_exts arrays. They remain unused until allocation of obj_exts
    -    arrays for normal kmalloc caches happens.
    +    KMALLOC_NO_OBJ_EXT caches are created with SLAB_NO_OBJ_EXT flag when
    +    either 1) memory allocation profiling is not permanently disabled,
    +    or 2) kmalloc types with a priority higher than KMALLOC_CGROUP are
    +    aliased with KMALLOC_NORMAL.
     
         Sheaf bootstrapping for KMALLOC_NO_OBJ_EXT caches now must be deferred
         because allocation of a barn can trigger obj_exts array allocation of
    @@ Commit message
         Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
     
      ## include/linux/slab.h ##
    +@@ include/linux/slab.h: enum kmalloc_cache_type {
    + #endif
    + #ifndef CONFIG_MEMCG
    + 	KMALLOC_CGROUP = KMALLOC_NORMAL,
    ++#endif
    ++#ifndef CONFIG_SLAB_OBJ_EXT
    ++	KMALLOC_NO_OBJ_EXT = KMALLOC_NORMAL,
    + #endif
    + 	KMALLOC_PARTITION_START = KMALLOC_NORMAL,
    + 	KMALLOC_PARTITION_END = KMALLOC_PARTITION_START + KMALLOC_PARTITION_CACHES_NR,
     @@ include/linux/slab.h: enum kmalloc_cache_type {
      #endif
      #ifdef CONFIG_MEMCG
    @@ mm/slab.h: static inline unsigned int size_index_elem(unsigned int bytes)
      	unsigned int index;
     +	enum kmalloc_cache_type type = kmalloc_type(flags, token);
     +
    -+#ifdef CONFIG_SLAB_OBJ_EXT
     +	if (alloc_flags & SLAB_ALLOC_NO_OBJ_EXT)
     +		type = KMALLOC_NO_OBJ_EXT;
    -+#endif
      
      	if (!b)
     -		b = &kmalloc_caches[kmalloc_type(flags, token)];
    @@ mm/slab.h: static inline bool is_kmalloc_normal(struct kmem_cache *s)
      }
      
      bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj);
    +@@ mm/slab.h: static inline void metadata_access_disable(void)
    + 	kasan_enable_current();
    + }
    + 
    ++/*
    ++ * Return true if KMALLOC_NORMAL caches may need obj_exts arrays.
    ++ *
    ++ * Memory allocation profiling requires obj_exts for all caches.
    ++ * Memcg usually doesn't need them for normal kmalloc caches, but kmalloc types
    ++ * with a priority higher than KMALLOC_CGROUP can be aliased with KMALLOC_NORMAL.
    ++ */
    ++static inline bool need_kmalloc_no_objext(void)
    ++{
    ++	if (!mem_alloc_profiling_permanently_disabled())
    ++		return true;
    ++
    ++	if (!mem_cgroup_kmem_disabled() &&
    ++			(KMALLOC_NORMAL == KMALLOC_RECLAIM))
    ++		return true;
    ++
    ++	return false;
    ++}
    ++
    + #ifdef CONFIG_SLAB_OBJ_EXT
    + 
    + /*
     
      ## mm/slab_common.c ##
     @@ mm/slab_common.c: u8 kmalloc_size_index[24] __ro_after_init = {
    @@ mm/slab_common.c: EXPORT_SYMBOL(kmalloc_size_roundup);
      }
      
     @@ mm/slab_common.c: new_kmalloc_cache(int idx, enum kmalloc_cache_type type)
    - 		flags |= SLAB_NO_MERGE;
    - #endif
    - 
    -+#ifdef CONFIG_SLAB_OBJ_EXT
    -+	if (type == KMALLOC_NO_OBJ_EXT)
    + 			return;
    + 		}
    + 		flags |= SLAB_ACCOUNT;
    ++	} else if (IS_ENABLED(CONFIG_SLAB_OBJ_EXT) && type == KMALLOC_NO_OBJ_EXT) {
    ++		if (!need_kmalloc_no_objext()) {
    ++			kmalloc_caches[type][idx] = kmalloc_caches[KMALLOC_NORMAL][idx];
    ++			return;
    ++		}
     +		flags |= SLAB_NO_OBJ_EXT | SLAB_NO_MERGE;
    -+#endif
    -+
    - 	/*
    - 	 * If CONFIG_MEMCG is enabled, disable cache merging for
    - 	 * KMALLOC_NORMAL caches.
    + 	} else if (IS_ENABLED(CONFIG_ZONE_DMA) && (type == KMALLOC_DMA)) {
    + 		flags |= SLAB_CACHE_DMA;
    + 	}
     
      ## mm/slub.c ##
     @@ mm/slub.c: static inline void init_slab_obj_exts(struct slab *slab)
    @@ mm/slub.c: int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s,
     +	 * However, normal kmalloc caches must allocate them from
     +	 * KMALLOC_NO_OBJ_EXT caches to prevent recursion.
     +	 */
    -+	if (is_kmalloc_normal(s))
    ++	if (is_kmalloc_normal(s)) {
    ++		VM_WARN_ON_ONCE(!need_kmalloc_no_objext());
     +		alloc_flags |= SLAB_ALLOC_NO_OBJ_EXT;
    ++	}
      
     -	sz = obj_exts_alloc_size(s, slab, gfp);
     +	alloc_flags &= ~SLAB_ALLOC_NEW_SLAB;

---
Harry Yoo (Oracle) (4):
      mm/slab: fix a memory leak due to bootstrapping sheaves twice
      mm/slab: decouple SLAB_NO_SHEAVES from SLAB_NO_OBJ_EXT
      lib/alloc_tag: introduce mem_alloc_profiling_permanently_disabled()
      mm/slab: prevent unbounded recursion in free path with new kmalloc type

 include/linux/alloc_tag.h |   3 ++
 include/linux/slab.h      |  19 +++++++-
 lib/alloc_tag.c           |   9 ++++
 mm/slab.h                 |  32 +++++++++++--
 mm/slab_common.c          |  19 +++++++-
 mm/slub.c                 | 111 ++++++++++++++++++++--------------------------
 6 files changed, 123 insertions(+), 70 deletions(-)
---
base-commit: 72bb229f9161a1efcd5df32141b69fcc6ae81a13
change-id: 20260702-kmalloc-no-objext-2619c1e06083

Best regards,
-- 
Harry Yoo (Oracle) <harry@kernel.org>


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

end of thread, other threads:[~2026-07-14 15:42 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-13 14:28 [PATCH slab/for-next-fixes v3 0/4] mm/slab: fix unbounded recursion in free path with memalloc profiling Harry Yoo (Oracle)
2026-07-13 14:28 ` [PATCH slab/for-next-fixes v3 1/4] mm/slab: fix a memory leak due to bootstrapping sheaves twice Harry Yoo (Oracle)
2026-07-13 15:30   ` Suren Baghdasaryan
2026-07-13 14:28 ` [PATCH slab/for-next-fixes v3 2/4] mm/slab: decouple SLAB_NO_SHEAVES from SLAB_NO_OBJ_EXT Harry Yoo (Oracle)
2026-07-13 15:37   ` Suren Baghdasaryan
2026-07-13 14:28 ` [PATCH slab/for-next-fixes v3 3/4] lib/alloc_tag: introduce mem_alloc_profiling_permanently_disabled() Harry Yoo (Oracle)
2026-07-13 15:43   ` Suren Baghdasaryan
2026-07-13 16:15     ` Vlastimil Babka (SUSE)
2026-07-13 16:28       ` Harry Yoo
2026-07-14 14:37         ` Suren Baghdasaryan
2026-07-13 14:28 ` [PATCH slab/for-next-fixes v3 4/4] mm/slab: prevent unbounded recursion in free path with new kmalloc type Harry Yoo (Oracle)
2026-07-13 17:08   ` Suren Baghdasaryan
2026-07-14  5:17     ` Harry Yoo
2026-07-14  9:12       ` Vlastimil Babka (SUSE)
2026-07-14 14:27         ` Suren Baghdasaryan
2026-07-14 15:21   ` Vlastimil Babka (SUSE)
2026-07-14 15:42 ` [PATCH slab/for-next-fixes v3 0/4] mm/slab: fix unbounded recursion in free path with memalloc profiling Vlastimil Babka (SUSE)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.