Re: [PATCH] block: fix pages array leak in bio_map_user_iov error path
From: 尹欣
Date: Mon May 18 2026 - 04:44:47 EST
> From: "Xin Yin"<yinxin.x@xxxxxxxxxxxxx>
> Date: Sat, May 9, 2026, 12:23
> Subject: [PATCH] block: fix pages array leak in bio_map_user_iov error path
> To: <axboe@xxxxxxxxx>, <dhowells@xxxxxxxxxx>
> Cc: <linux-block@xxxxxxxxxxxxxxx>, <linux-kernel@xxxxxxxxxxxxxxx>, "Xin Yin"<yinxin.x@xxxxxxxxxxxxx>, <stable@xxxxxxxxxxxxxxx>
> 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
>
Hi Jens
Gentle ping on this patch.
This patch fixes a memory leak in bio_map_user_iov() that only affects
stable kernels (6.5+) carrying commit 403b6fb8dac1. Mainline resolved
this through a later refactoring that removed the affected code path
entirely, so there is no upstream commit to backport.
Could this be picked up for 6.6.y?
Thanks,
Xin Yin