]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
alloc_tag: fix boot failure due to NULL pointer dereference
authorRan Xiaokai <ran.xiaokai@zte.com.cn>
Fri, 26 Sep 2025 08:06:59 +0000 (08:06 +0000)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 28 Sep 2025 18:51:33 +0000 (11:51 -0700)
There is a boot failure when both CONFIG_DEBUG_KMEMLEAK and
CONFIG_MEM_ALLOC_PROFILING are enabled.

BUG: kernel NULL pointer dereference, address: 0000000000000000
RIP: 0010:__alloc_tagging_slab_alloc_hook+0x181/0x2f0
Call Trace:
 kmem_cache_alloc_noprof+0x1c8/0x5c0
 __alloc_object+0x2f/0x290
 __create_object+0x22/0x80
 kmemleak_init+0x122/0x190
 mm_core_init+0xb6/0x160
 start_kernel+0x39f/0x920
 x86_64_start_reservations+0x18/0x30
 x86_64_start_kernel+0x104/0x120
 common_startup_64+0x12c/0x138

In kmemleak, mem_pool_alloc() directly calls kmem_cache_alloc_noprof(), as
a result, current->alloc_tag is NULL, leading to a null pointer
dereference.

Move the checks for SLAB_NO_OBJ_EXT, SLAB_NOLEAKTRACE, and
__GFP_NO_OBJ_EXT to the parent function __alloc_tagging_slab_alloc_hook()
to fix this.

Also this distinguishes the SLAB_NOLEAKTRACE case between the actual
memory allocation failures case, make CODETAG_FLAG_INACCURATE more
accurate.

Link: https://lkml.kernel.org/r/20250926080659.741991-1-ranxiaokai627@163.com
Fixes: b9e2f58ffb84 ("alloc_tag: mark inaccurate allocation counters in /proc/allocinfo output")
Signed-off-by: Ran Xiaokai <ran.xiaokai@zte.com.cn>
Reviewed-by: Harry Yoo <harry.yoo@oracle.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Cc: Christoph Lameter (Ampere) <cl@gentwo.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Usama Arif <usamaarif642@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/slub.c

index 9c04f29ee8deec6fcf666e7bfb9045aeb45242d0..9d73cca9f1de8b0235f78a4cdd7b6356920d74a5 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2109,15 +2109,6 @@ prepare_slab_obj_exts_hook(struct kmem_cache *s, gfp_t flags, void *p)
 {
        struct slab *slab;
 
-       if (!p)
-               return NULL;
-
-       if (s->flags & (SLAB_NO_OBJ_EXT | SLAB_NOLEAKTRACE))
-               return NULL;
-
-       if (flags & __GFP_NO_OBJ_EXT)
-               return NULL;
-
        slab = virt_to_slab(p);
        if (!slab_obj_exts(slab) &&
            alloc_slab_obj_exts(slab, s, flags, false)) {
@@ -2135,6 +2126,15 @@ __alloc_tagging_slab_alloc_hook(struct kmem_cache *s, void *object, gfp_t flags)
 {
        struct slabobj_ext *obj_exts;
 
+       if (!object)
+               return;
+
+       if (s->flags & (SLAB_NO_OBJ_EXT | SLAB_NOLEAKTRACE))
+               return;
+
+       if (flags & __GFP_NO_OBJ_EXT)
+               return;
+
        obj_exts = prepare_slab_obj_exts_hook(s, flags, object);
        /*
         * Currently obj_exts is used only for allocation profiling.