mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Vlastimil Babka (SUSE)" <vbabka@kernel.org>
To: Harry Yoo <harry@kernel.org>, Suren Baghdasaryan <surenb@google.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Hao Li <hao.li@linux.dev>, Christoph Lameter <cl@gentwo.org>,
	David Rientjes <rientjes@google.com>,
	Roman Gushchin <roman.gushchin@linux.dev>,
	"Liam R. Howlett" <liam@infradead.org>, Hao Ge <hao.ge@linux.dev>,
	Kees Cook <kees@kernel.org>, Pedro Falcato <pfalcato@suse.de>,
	Shakeel Butt <shakeel.butt@linux.dev>,
	Danielle Constantino <dcostantino@meta.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH slab/for-next-fixes v3 4/4] mm/slab: prevent unbounded recursion in free path with new kmalloc type
Date: Tue, 14 Jul 2026 11:12:38 +0200	[thread overview]
Message-ID: <87f607bb-3766-4b90-b3cc-a98d3cadf760@kernel.org> (raw)
In-Reply-To: <121dda1a-f050-4035-93c0-6a36278e50b7@kernel.org>

On 7/14/26 07:17, Harry Yoo wrote:
> 
> On 7/14/26 2:08 AM, Suren Baghdasaryan wrote:
>> On Mon, Jul 13, 2026 at 7:29 AM Harry Yoo (Oracle) <harry@kernel.org> wrote:
>>> @@ -386,12 +387,17 @@ static inline unsigned int size_index_elem(unsigned int bytes)
>>>   * KMALLOC_MAX_CACHE_SIZE and the caller must check that.
>>>   */
>>>  static inline struct kmem_cache *
>>> -kmalloc_slab(size_t size, kmem_buckets *b, gfp_t flags, kmalloc_token_t token)
>>> +kmalloc_slab(size_t size, kmem_buckets *b, gfp_t flags, kmalloc_token_t token,
>>> +            unsigned int alloc_flags)
>>>  {
>>>         unsigned int index;
>>> +       enum kmalloc_cache_type type = kmalloc_type(flags, token);
>>> +
>>> +       if (alloc_flags & SLAB_ALLOC_NO_OBJ_EXT)
>>> +               type = KMALLOC_NO_OBJ_EXT;
> 
> Hi Suren, thanks for the reviews.
> It's indeed helpful to have an eye for those bugfixes.
> 
>> Why not let kmalloc_type() handle alloc_flags?
> 
> Good point!
> 
>> Other users (there are
>> only 4 of them) can pass SLAB_ALLOC_DEFAULT. That seems cleaner to me
>> and more robust.
> 
> Hmm, there was a reason... *checks notes*, oh, there is no note.
> IIRC I was afraid of exposing SLAB_ALLOC_* flags to arbitrary users.

Hm good point, they are in mm/slab.h and kmalloc_type() needs to be in the
public include/linux/slab.h. Given its usage in __builtin_constant_p(size)
paths of kmalloc[_node] I would rather not complicate it (even if a
hardcoded SLAB_ALLOC_DEFAULT should eliminate the extra code).
So I'd rather keep KMALLOC_NO_OBJ_EXT handling hidden in mm/ as long as it's
possible.

> should probably fine as long as it's not used in
> kmalloc/kmem_cache_alloc() APIs, not sure.
> 
>>>         if (!b)
>>> -               b = &kmalloc_caches[kmalloc_type(flags, token)];
>>> +               b = &kmalloc_caches[type];
>>>         if (size <= 192)
>>>                 index = kmalloc_size_index[size_index_elem(size)];
>>>         else
>>> diff --git a/mm/slab_common.c b/mm/slab_common.c
>>> index b6426d7ceec9..03ecac12cd86 100644
>>> --- a/mm/slab_common.c
>>> +++ b/mm/slab_common.c
>>> @@ -957,6 +968,12 @@ new_kmalloc_cache(int idx, enum kmalloc_cache_type type)
>>>                         return;
>>>                 }
>>>                 flags |= SLAB_ACCOUNT;
>>> +       } else if (IS_ENABLED(CONFIG_SLAB_OBJ_EXT) && type == KMALLOC_NO_OBJ_EXT) {
>> 
>> Hmm, you have to check IS_ENABLED(CONFIG_SLAB_OBJ_EXT) here because
>> KMALLOC_NO_OBJ_EXT can be aliased with KMALLOC_NORMAL... Could we
>> instead have a helper function like this (maybe with a better name):
> 
> Hmm that's fine, but I think that bit should not be part of -stable
> fixes at least. Here I tried to make it consistent with KMALLOC_RECLAIM
> and KMALLOC_DMA :)

Agreed.

>> #ifdef CONFIG_SLAB_OBJ_EXT
>> bool is_kmalloc_no_obj_ext_type(type) { return type == KMALLOC_NO_OBJ_EXT; }
>> #else
>> bool is_kmalloc_no_obj_ext_type(type) { return false; }
>> #endif
>> ?
> 
> is_kmalloc_no_obj_ext_type(),
> kmalloc_type_is_no_obj_ext(),
> is_kmalloc_type_no_obj_ext(),
> ...
> 
> naming is hard, ugh :)
> 
>> 
>>> +               if (!need_kmalloc_no_objext()) {
>>> +                       kmalloc_caches[type][idx] = kmalloc_caches[KMALLOC_NORMAL][idx];
>> 
>> Could kmalloc_caches[KMALLOC_NORMAL][idx] be NULL here?
> 
> No. KMALLOC_NORMAL caches are created before all other kmalloc
> caches.
> 
> IIRC checking if kmalloc_caches[KMALLOC_NORMAL][idx] is NULL was added
> by commit 963e84b0f262 ("mm/slab: limit kmalloc() minimum alignment
> to dma_get_cache_alignment()") to avoid creating kmalloc caches of same
> type and size due to minimum alignment.
> 
>> In general why do we special-case and do an early exit here?
>>
>> Can we do instead:
>> 
>> if (need_kmalloc_no_objext())
>>     flags |= SLAB_NO_OBJ_EXT | SLAB_NO_MERGE;
>> 
>> and use the common path?
> 
> Hmm, but even without SLAB_NO_MERGE, we often end up not merging
> kmalloc caches e.g.) because of non-zero s->usersize.
> 
> I think that's why we do special-case and an early exit?
> 
> We could probably do some refactoring to change that, but in general
> I'm afraid of backporting refactoring work to -stable because I fear
> introducing very subtle behavioral changes that nobody would notice.

Agreed, let's keep hotfixes as minimal as possible and refactor later.

>>> +                       return;
>>> +               }
>>> +               flags |= SLAB_NO_OBJ_EXT | SLAB_NO_MERGE;
>>>         } else if (IS_ENABLED(CONFIG_ZONE_DMA) && (type == KMALLOC_DMA)) {
>>>                 flags |= SLAB_CACHE_DMA;
>>>         }
>>> diff --git a/mm/slub.c b/mm/slub.c
>>> index abe748b7dddb..a34f9b8770dc 100644
>>> --- a/mm/slub.c
>>> +++ b/mm/slub.c
>>> @@ -2168,14 +2132,20 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s,
>>>         unsigned long new_exts;
>>>         unsigned long old_exts;
>>>         struct slabobj_ext *vec;
>>> -       size_t sz;
>>> +       size_t sz = sizeof(struct slabobj_ext) * slab->objects;
>>>
>>>         gfp &= ~OBJCGS_CLEAR_MASK;
>>> -       /* Prevent recursive extension vector allocation */
>>> -       alloc_flags |= SLAB_ALLOC_NO_RECURSE;
>>> -       alloc_flags &= ~SLAB_ALLOC_NEW_SLAB;
>>> +       /*
>>> +        * In most cases, obj_exts arrays are allocated from normal kmalloc.
>>> +        * However, normal kmalloc caches must allocate them from
>>> +        * KMALLOC_NO_OBJ_EXT caches to prevent recursion.
>> 
>> For debugging it would have been convenient to allocate all obj_ext
>> vectors from dedicated caches... Maybe we can do that for
>> CONFIG_DEBUG_VM or someday when we add CONFIG_OBJ_EXT_DEBUG? Anyway,
>> not really a complaint but a wish.
> 
> Vlastimil and I had a conversation on always (even w/o debug options)
> having dedicated caches (primarily to separate lifetime and for
> simplicity), it would be interesting to explore.
> 
> https://lore.kernel.org/all/2436707a-b6ab-45ec-98e5-538e18589462@kernel.org
> 


  reply	other threads:[~2026-07-14  9:12 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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-16  2:31     ` Harry Yoo
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-16  2:34           ` Harry Yoo
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) [this message]
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)
2026-07-15  7:46   ` Harry Yoo
2026-07-16 18:05 ` Shakeel Butt
2026-07-17  4:09   ` Harry Yoo
2026-07-16 19:37 ` Shakeel Butt
2026-07-17  1:16   ` Hao Ge
2026-07-17 15:18     ` Shakeel Butt
2026-07-17  4:10   ` Harry Yoo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87f607bb-3766-4b90-b3cc-a98d3cadf760@kernel.org \
    --to=vbabka@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=cl@gentwo.org \
    --cc=dcostantino@meta.com \
    --cc=hao.ge@linux.dev \
    --cc=hao.li@linux.dev \
    --cc=harry@kernel.org \
    --cc=kees@kernel.org \
    --cc=liam@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=pfalcato@suse.de \
    --cc=rientjes@google.com \
    --cc=roman.gushchin@linux.dev \
    --cc=shakeel.butt@linux.dev \
    --cc=surenb@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox