]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mm/kmsan: fix kmsan kmalloc hook when no stack depots are allocated yet
authorAleksei Nikiforov <aleksei.nikiforov@linux.ibm.com>
Tue, 30 Sep 2025 11:56:01 +0000 (13:56 +0200)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 10 Nov 2025 05:19:42 +0000 (21:19 -0800)
If no stack depot is allocated yet, due to masking out __GFP_RECLAIM flags
kmsan called from kmalloc cannot allocate stack depot.  kmsan fails to
record origin and report issues.  This may result in KMSAN failing to
report issues.

Reusing flags from kmalloc without modifying them should be safe for kmsan.
For example, such chain of calls is possible:
test_uninit_kmalloc -> kmalloc -> __kmalloc_cache_noprof ->
slab_alloc_node -> slab_post_alloc_hook ->
kmsan_slab_alloc -> kmsan_internal_poison_memory.

Only when it is called in a context without flags present should
__GFP_RECLAIM flags be masked.

With this change all kmsan tests start working reliably.

Eric reported:

: Yes, KMSAN seems to be at least partially broken currently.  Besides the
: fact that the kmsan KUnit test is currently failing (which I reported at
: https://lore.kernel.org/r/20250911175145.GA1376@sol), I've confirmed that
: the poly1305 KUnit test causes a KMSAN warning with Aleksei's patch
: applied but does not cause a warning without it.  The warning did get
: reached via syzbot somehow
: (https://lore.kernel.org/r/751b3d80293a6f599bb07770afcef24f623c7da0.1761026343.git.xiaopei01@kylinos.cn/),
: so KMSAN must still work in some cases.  But it didn't work for me.

Link: https://lkml.kernel.org/r/20250930115600.709776-2-aleksei.nikiforov@linux.ibm.com
Link: https://lkml.kernel.org/r/20251022030213.GA35717@sol
Fixes: 97769a53f117 ("mm, bpf: Introduce try_alloc_pages() for opportunistic page allocation")
Signed-off-by: Aleksei Nikiforov <aleksei.nikiforov@linux.ibm.com>
Reviewed-by: Alexander Potapenko <glider@google.com>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Ilya Leoshkevich <iii@linux.ibm.com>
Cc: Marco Elver <elver@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/kmsan/core.c
mm/kmsan/hooks.c
mm/kmsan/shadow.c

index 8bca7fece47f0e1eb947d709b1204baad14f1ea7..35ceaa8adb41ebe7b6d51b689fa9a66d12eab013 100644 (file)
@@ -72,9 +72,6 @@ depot_stack_handle_t kmsan_save_stack_with_flags(gfp_t flags,
 
        nr_entries = stack_trace_save(entries, KMSAN_STACK_DEPTH, 0);
 
-       /* Don't sleep. */
-       flags &= ~(__GFP_DIRECT_RECLAIM | __GFP_KSWAPD_RECLAIM);
-
        handle = stack_depot_save(entries, nr_entries, flags);
        return stack_depot_set_extra_bits(handle, extra);
 }
index 2cee59d89c808f7a6b169856bca9b2ff5b0dc252..8f22d1f229813f0fc393affee826fd2e414533cc 100644 (file)
@@ -84,7 +84,8 @@ void kmsan_slab_free(struct kmem_cache *s, void *object)
        if (s->ctor)
                return;
        kmsan_enter_runtime();
-       kmsan_internal_poison_memory(object, s->object_size, GFP_KERNEL,
+       kmsan_internal_poison_memory(object, s->object_size,
+                                    GFP_KERNEL & ~(__GFP_RECLAIM),
                                     KMSAN_POISON_CHECK | KMSAN_POISON_FREE);
        kmsan_leave_runtime();
 }
@@ -114,7 +115,8 @@ void kmsan_kfree_large(const void *ptr)
        kmsan_enter_runtime();
        page = virt_to_head_page((void *)ptr);
        KMSAN_WARN_ON(ptr != page_address(page));
-       kmsan_internal_poison_memory((void *)ptr, page_size(page), GFP_KERNEL,
+       kmsan_internal_poison_memory((void *)ptr, page_size(page),
+                                    GFP_KERNEL & ~(__GFP_RECLAIM),
                                     KMSAN_POISON_CHECK | KMSAN_POISON_FREE);
        kmsan_leave_runtime();
 }
index 54f3c3c962f07842587b8cde6f3b7247ca6de8dd..55fdea199aaf0199cb319ad02331563c2c023ca6 100644 (file)
@@ -208,7 +208,7 @@ void kmsan_free_page(struct page *page, unsigned int order)
                return;
        kmsan_enter_runtime();
        kmsan_internal_poison_memory(page_address(page), page_size(page),
-                                    GFP_KERNEL,
+                                    GFP_KERNEL & ~(__GFP_RECLAIM),
                                     KMSAN_POISON_CHECK | KMSAN_POISON_FREE);
        kmsan_leave_runtime();
 }