mmc: mmc_test: Fix __counted_by handling after kzalloc_flex() conversion

Fix logic issues introduced by the kzalloc_flex() conversion in
mmc_test_alloc_mem() due to interaction with the __counted_by
annotation on the flexible array.

Bounds-checking sanitizers rely on the counter field reflecting the
allocated array size before any array access occurs. However, use
mem->cnt both as the allocation size and as the runtime insertion
index, causing incorrect indexing and potentially invalid bounds
tracking.

Initialize mem->cnt to the maximum allocated number of segments
immediately after kzalloc_flex(), then use a separate local index
variable to track successfully allocated entries. Update mem->cnt to
the actual number of initialized elements before returning or entering
the cleanup path.

Also rewrite mmc_test_free_mem() to use a forward for-loop, improving
readability and ensuring only initialized entries are freed.

Fixes: c3126dccfd ("mmc: mmc_test: use kzalloc_flex")
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
This commit is contained in:
Lad Prabhakar 2026-06-02 21:13:44 +01:00 committed by Ulf Hansson
parent 521f39ca93
commit c35fac6481

View File

@ -318,9 +318,9 @@ static void mmc_test_free_mem(struct mmc_test_mem *mem)
{
if (!mem)
return;
while (mem->cnt--)
__free_pages(mem->arr[mem->cnt].page,
mem->arr[mem->cnt].order);
for (unsigned int i = 0; i < mem->cnt; i++)
__free_pages(mem->arr[i].page,
mem->arr[i].order);
kfree(mem);
}
@ -341,6 +341,7 @@ static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz,
unsigned long page_cnt = 0;
unsigned long limit = nr_free_buffer_pages() >> 4;
struct mmc_test_mem *mem;
unsigned int idx = 0;
if (max_page_cnt > limit)
max_page_cnt = limit;
@ -375,23 +376,26 @@ static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz,
goto out_free;
break;
}
mem->arr[mem->cnt].page = page;
mem->arr[mem->cnt].order = order;
mem->cnt += 1;
mem->arr[idx].page = page;
mem->arr[idx].order = order;
idx += 1;
if (max_page_cnt <= (1UL << order))
break;
max_page_cnt -= 1UL << order;
page_cnt += 1UL << order;
if (mem->cnt >= max_segs) {
if (idx >= mem->cnt) {
if (page_cnt < min_page_cnt)
goto out_free;
break;
}
}
mem->cnt = idx;
return mem;
out_free:
mem->cnt = idx;
mmc_test_free_mem(mem);
return NULL;
}