From: Shengming Hu _kmalloc_nolock_noprof() retries from the next kmalloc bucket when the initial allocation fails. The retry currently reuses `size` as the bucket selector and overwrites it with s->object_size + 1. That value is later passed as the original allocation size to __slab_alloc_node(), slab_post_alloc_hook() and kasan_kmalloc(). On a successful retry this makes KASAN/slub-debug observe the retry bucket selector rather than the caller requested size, potentially widening the valid kmalloc range and hiding overflows. Keep a separate `bucket_size` for choosing the retry cache and preserve `size`. Fixes: ("slab: Introduce kmalloc_nolock() and kfree_nolock()") Signed-off-by: Shengming Hu --- mm/slub.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 67abbbf68fc1..6a2b3ade3611 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -5350,6 +5350,7 @@ EXPORT_SYMBOL(__kmalloc_noprof); void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, int node) { gfp_t alloc_gfp = __GFP_NOWARN | __GFP_NOMEMALLOC | gfp_flags; + size_t bucket_size = size; struct kmem_cache *s; bool can_retry = true; void *ret; @@ -5372,9 +5373,9 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in return NULL; retry: - if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) + if (unlikely(bucket_size > KMALLOC_MAX_CACHE_SIZE)) return NULL; - s = kmalloc_slab(size, NULL, alloc_gfp, PASS_TOKEN_PARAM(token)); + s = kmalloc_slab(bucket_size, NULL, alloc_gfp, PASS_TOKEN_PARAM(token)); if (!(s->flags & __CMPXCHG_DOUBLE) && !kmem_cache_debug(s)) /* @@ -5408,7 +5409,7 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in */ if (!ret && can_retry) { /* pick the next kmalloc bucket */ - size = s->object_size + 1; + bucket_size = s->object_size + 1; /* * Another alternative is to * if (memcg) alloc_gfp &= ~__GFP_ACCOUNT; -- 2.25.1