Commit 464b1c11 authored by Qing Wang's avatar Qing Wang Committed by Vlastimil Babka (SUSE)
Browse files

slab: fix memory leak when refill_sheaf() fails



When refill_sheaf() partially fills one sheaf (e.g., fills 5 objects
but need to fill 10), it will update sheaf->size and return -ENOMEM.
However, the callers (alloc_full_sheaf() and __pcs_replace_empty_main())
directly call free_empty_sheaf() on failure, which only does kfree(sheaf),
causing the partially allocated objects memory in sheaf->objects[] leaked.

Fix this by calling sheaf_flush_unused() before free_empty_sheaf() to
free objects of sheaf->objects[]. And also add a WARN_ON() in
free_empty_sheaf() to catch any future cases where a non-empty sheaf is
being freed.

Fixes: ed30c4ad ("slab: add optimized sheaf refill from partial list")
Signed-off-by: default avatarQing Wang <wangqing7171@gmail.com>
Link: https://patch.msgid.link/20260311093617.4155965-1-wangqing7171@gmail.com


Reviewed-by: default avatarHarry Yoo <harry.yoo@oracle.com>
Reviewed-by: default avatarHao Li <hao.li@linux.dev>
Signed-off-by: default avatarVlastimil Babka (SUSE) <vbabka@kernel.org>
parent 8dafa9f5
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2790,6 +2790,7 @@ static void free_empty_sheaf(struct kmem_cache *s, struct slab_sheaf *sheaf)
	if (s->flags & SLAB_KMALLOC)
		mark_obj_codetag_empty(sheaf);

	VM_WARN_ON_ONCE(sheaf->size > 0);
	kfree(sheaf);

	stat(s, SHEAF_FREE);
@@ -2821,6 +2822,7 @@ static int refill_sheaf(struct kmem_cache *s, struct slab_sheaf *sheaf,
	return 0;
}

static void sheaf_flush_unused(struct kmem_cache *s, struct slab_sheaf *sheaf);

static struct slab_sheaf *alloc_full_sheaf(struct kmem_cache *s, gfp_t gfp)
{
@@ -2830,6 +2832,7 @@ static struct slab_sheaf *alloc_full_sheaf(struct kmem_cache *s, gfp_t gfp)
		return NULL;

	if (refill_sheaf(s, sheaf, gfp | __GFP_NOMEMALLOC | __GFP_NOWARN)) {
		sheaf_flush_unused(s, sheaf);
		free_empty_sheaf(s, sheaf);
		return NULL;
	}
@@ -4616,6 +4619,7 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,
			 * we must be very low on memory so don't bother
			 * with the barn
			 */
			sheaf_flush_unused(s, empty);
			free_empty_sheaf(s, empty);
		}
	} else {