Re: [PATCH] mm/slub: serve slabobj_ext array from a strictly larger kmalloc cache

From: Harry Yoo

Date: Wed Jul 01 2026 - 00:32:06 EST




On 7/1/26 8:55 AM, Suren Baghdasaryan wrote:
> On Tue, Jun 30, 2026 at 8:27 AM Harry Yoo <harry@xxxxxxxxxx> wrote:
>>> I'll also give it some thought to see if there is maybe a different
>>> way to fix this that would be easy to backport.
>>
>> Thanks, let's discuss!
>
> So, below patch is based on stable linux-7.1.y branch and I think it's
> the simplest backportable way to fix this issue. Build-tested only, so
> use just as a prototype.

Thanks!

> Not sure if making buckets parameter
> unconditional from CONFIG_SLAB_BUCKETS has side-effects...

Increased binary size and register pressure IIRC
https://lore.kernel.org/linux-mm/d0fe363c-2e8f-44a4-9b64-3fa3ba9a5773@xxxxxxxxxx

> Attaching the patch as well since I'm sure gmail will butcher the tabs.
>
> The fix for 7.2 should be much simpler using a new flag in
> kmalloc_flags() for obj_ext vector allocations and serving these from
> a dedicated cache.

...which means, in 7.2, it will have a new KMALLOC_TYPE and now
kmalloc_type() and kmalloc_slab() will select the cache based on GFP
flags AND slab's alloc_flags (based on SLAB_ALLOC_NO_RECURSE, this is
new)

Hmm, wait.

We can do that in pre-7.2 kernels, by teaching kmalloc_type() and
kmalloc_slab() select the new KMALLOC_TYPE based on __GFP_NO_OBJ_EXT?

e.g.) Select the new KMALLOC_TYPE when KMALLOC_NOT_NORMAL_BITS is not
set AND __GFP_NO_OBJ_EXT is set.

This doesn't require kmem_buckets and should be much simpler.

> Please let me know what you think:

So I think we don't need kmem_buckets for minimal fixes?

> ---
> include/linux/slab.h | 42 +++++++++++++++++++++---------
> mm/slub.c | 61 +++++++++++---------------------------------
> 2 files changed, 45 insertions(+), 58 deletions(-)
>
> diff --git a/include/linux/slab.h b/include/linux/slab.h
> index 2b5ab488e96b..2d4a6e3064a3 100644
> --- a/include/linux/slab.h
> +++ b/include/linux/slab.h
> @@ -618,6 +618,10 @@ static inline unsigned int arch_slab_minalign(void)
> #define RANDOM_KMALLOC_CACHES_NR 0
> #endif
>
> +#if defined(CONFIG_MEM_ALLOC_PROFILING) && defined(CONFIG_SLUB_TINY)
> +#define OBJ_EXT_VEC_CACHE
> +#endif

Should be || instead of &&

> /*
> * Whenever changing this, take care of that kmalloc_type() and
> * create_kmalloc_caches() still work as intended.
> @@ -646,6 +650,9 @@ enum kmalloc_cache_type {
> #endif
> #ifdef CONFIG_MEMCG
> KMALLOC_CGROUP,
> +#endif
> +#ifdef OBJ_EXT_VEC_CACHE
> + KMALLOC_OBJ_EXT_VEC,
> #endif
> NR_KMALLOC_TYPES
> };
> @@ -654,6 +661,18 @@ typedef struct kmem_cache *
> kmem_buckets[KMALLOC_SHIFT_HIGH + 1];
>
> extern kmem_buckets kmalloc_caches[NR_KMALLOC_TYPES];
>
> +#ifdef OBJ_EXT_VEC_CACHE
> +static inline kmem_buckets *obj_ext_vec_buckets(void)
> +{
> + return &kmalloc_caches[KMALLOC_OBJ_EXT_VEC];
> +}
> +#else
> +static inline kmem_buckets *obj_ext_vec_buckets(void)
> +{
> + return NULL;
> +}
> +#endif

This is bit weird because it creates a new kmalloc type while using
kmem_buckets. Conceptually, a kmem_buckets can be thought as
a KMALLOC_TYPE, but created by kmem_buckets_create().

Security folks introduced this to isolate some kmalloc allocations from
of varying size (e.g., memdup_user, msg_msg where users can control the
size of allocation) from the rest of kmalloc caches.

> /*
> * Define gfp bits that should not be set for KMALLOC_NORMAL.
> */

--
Cheers,
Harry / Hyeonggon

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature