[PATCH] block: fix pages array leak in bio_map_user_iov error path
From: Xin Yin
Date: Sat May 09 2026 - 00:25:00 EST
In bio_map_user_iov(), when iov_iter_extract_pages() is called with pages
set to NULL (because nr_vecs > UIO_FASTIOV), want_pages_array() internally
allocates a pages array via kvmalloc_array(). If iov_iter_extract_pages()
subsequently returns bytes <= 0 (e.g., due to pin_user_pages_fast()
failure), the code jumps to out_unmap without freeing the dynamically
allocated pages array, causing a memory leak detectable by kmemleak.
This can be triggered from userspace by issuing an SG_IO v4 ioctl on a
bsg device with a large din_xfer_len and an invalid din_xferp (mapped
PROT_NONE), which causes pin_user_pages_fast() to fail after the pages
array has already been allocated by want_pages_array().
The kmemleak backtrace looks like:
unreferenced object 0xffff... (size 2048):
backtrace (crc 0):
kvmalloc_node+0x...
want_pages_array+0x...
iov_iter_extract_pages+0x...
bio_map_user_iov+0x...
blk_rq_map_user_iov+0x...
blk_rq_map_user+0x...
bsg_transport_sg_io_fn+0x...
Fix this by freeing the dynamically allocated pages array (when it
differs from the on-stack stack_pages) before jumping to the error path.
Fixes: 403b6fb8dac1 ("block: convert bio_map_user_iov to use iov_iter_extract_pages")
Cc: stable@xxxxxxxxxxxxxxx # 6.5+
Signed-off-by: Xin Yin <yinxin.x@xxxxxxxxxxxxx>
---
block/blk-map.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/block/blk-map.c b/block/blk-map.c
index 0aadbaf7a9ddd..5b9f14caad4f9 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -304,6 +304,8 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
bytes = iov_iter_extract_pages(iter, &pages, LONG_MAX,
nr_vecs, extraction_flags, &offs);
if (unlikely(bytes <= 0)) {
+ if (pages != stack_pages)
+ kvfree(pages);
ret = bytes ? bytes : -EFAULT;
goto out_unmap;
}
--
2.20.1