Re: [BUG] WARNING in alloc_slab_obj_exts triggered by __d_alloc
From: Harry Yoo
Date: Mon Mar 09 2026 - 00:34:14 EST
On Mon, Mar 09, 2026 at 11:14:58AM +0800, Zw Tang wrote:
> Hi,
>
> I encountered a WARNING in alloc_slab_obj_exts() while running a
> syzkaller-generated reproducer on Linux 7.0-rc2.
>
> The warning is triggered during dentry allocation (__d_alloc) after
> mounting a crafted ext4 filesystem image.
>
> Kernel
> git tree: torvalds/linux
> commit: 0031c06807cfa8aa51a759ff8aa09e1aa48149af
> kernel version:Linux 7.0.0-rc2-00057-g0031c06807cf
> hardware: QEMU Ubuntu 24.10
>
> I was able to reproduce this issue reliably using the attached
> reproducer.
Hi, thanks for the report!
> Reproducer:
> C reproducer: https://pastebin.com/raw/eHjm2Aw6
> console output: https://pastebin.com/raw/FQAhquTy
> kernel config: pastebin.com/raw/CnHdTQNm
a few notable config options:
CONFIG_SLUB_TINY=y (which implies KMALLOC_RECLAIM = KMALLOC_NORMAL)
# CONFIG_MEM_ALLOC_PROFILING is not set
CONFIG_MEMCG=y
and also random kmalloc cache feature is not enabled.
> The warning originates from:
>
> mm/slub.c:2189
>
> Call trace:
>
> WARNING: mm/slub.c:2189 at alloc_slab_obj_exts+0x132/0x180
> CPU: 0 UID: 0 PID: 699 Comm: syz.0.118
The triggered warning is:
VM_WARN_ON_ONCE(virt_to_slab(vec) != NULL &&
virt_to_slab(vec)->slab_cache == s);
which means we may be creating a never-freed slab due to recursion.
obj_exts_alloc_size() is supposed to prevent this but it didn't.
Let's see why.
> Call Trace:
> <TASK>
> __memcg_slab_post_alloc_hook+0x130/0x460 mm/memcontrol.c:3234
> memcg_slab_post_alloc_hook mm/slub.c:2464 [inline]
> slab_post_alloc_hook.constprop.0+0x9c/0xf0 mm/slub.c:4526
> slab_alloc_node.constprop.0+0xaa/0x160 mm/slub.c:4844
> __do_kmalloc_node mm/slub.c:5237 [inline]
> __kmalloc_noprof+0x82/0x200 mm/slub.c:5250
> kmalloc_noprof include/linux/slab.h:954 [inline]
> __d_alloc+0x235/0x2f0 fs/dcache.c:1757
The gfp flag used by __d_alloc() is
GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE.
Looking at kmalloc_type(), when both __GFP_RECLAIMABLE and __GFP_ACCOUNT
flags are specified, __GFP_RECLAIMABLE has a higher priority.
That said, obj_exts_alloc_size() needs to handle CONFIG_SLUB_TINY
(KMALLOC_RECLAIM = KMALLOC_NORMAL) properly.
in obj_exts_alloc_size():
> /*
> * slabobj_ext array for KMALLOC_CGROUP allocations
> * are served from KMALLOC_NORMAL caches.
> */
> if (!mem_alloc_profiling_enabled())
> return sz;
I added this just to make sure we're not pessimizing when memory
profiling is not enabled. It turns out this part is incorrect,
and actually, redundant.
When memcg requested allocation, the snippet assumes that it would be
KMALLOC_CGROUP, but it turns out there is an exception:
SLUB_TINY with __GFP_ACCOUNT and __GFP_RECLAIMABLE specified.
This should be properly handled by:
> if (!is_kmalloc_normal(s))
> return sz;
I think this should work:
diff --git a/mm/slub.c b/mm/slub.c
index 0c906fefc31b..4759fe6aa60e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2119,13 +2119,6 @@ static inline size_t obj_exts_alloc_size(struct kmem_cache *s,
size_t sz = sizeof(struct slabobj_ext) * slab->objects;
struct kmem_cache *obj_exts_cache;
- /*
- * slabobj_ext array for KMALLOC_CGROUP allocations
- * are served from KMALLOC_NORMAL caches.
- */
- if (!mem_alloc_profiling_enabled())
- return sz;
-
if (sz > KMALLOC_MAX_CACHE_SIZE)
return sz;
> d_alloc_pseudo+0x1d/0x70 fs/dcache.c:1871
> alloc_path_pseudo fs/file_table.c:364 [inline]
> alloc_file_pseudo+0x64/0x140 fs/file_table.c:380
> __shmem_file_setup+0x136/0x270 mm/shmem.c:5863
> memfd_alloc_file+0x81/0x240 mm/memfd.c:471
> __do_sys_memfd_create mm/memfd.c:522 [inline]
> __se_sys_memfd_create mm/memfd.c:505 [inline]
> __x64_sys_memfd_create+0x205/0x440 mm/memfd.c:505
> do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> do_syscall_64+0x11d/0x5a0 arch/x86/entry/syscall_64.c:94
> entry_SYSCALL_64_after_hwframe+0x4b/0x53
>
> The issue happens after mounting an ext4 filesystem image via a loop
> device created from a compressed image in the reproducer.
>
> Relevant kernel messages:
>
> EXT4-fs (loop0): mounted filesystem
> 00000000-0000-0000-0000-000000000000 r/w without journal.
> EXT4-fs (loop3): Delayed block allocation failed for inode 18 at
> logical offset 768 with max blocks 2 with error 28
> EXT4-fs (loop3): This should not happen!! Data will be lost
>
> The WARNING occurs in alloc_slab_obj_exts(), which is related to slab
> object extension allocation.
>
> This may indicate a slab metadata inconsistency triggered by the
> filesystem state.
>
> Please let me know if additional debugging information would help.
>
> Thanks.
> Zw Tang
--
Cheers,
Harry / Hyeonggon