From 058fc59326af3350c6e830858e56d2aeecabe0a2 Mon Sep 17 00:00:00 2001 From: Jia Jia Date: Fri, 23 Oct 2026 18:40:35 +0800 Subject: [PATCH] vhost-scsi: fix page reference leak in misaligned I/O fallback iov_iter_get_pages2() returns a byte count that excludes the offset into the first page, but also returns a reference to that page in pages[]. On the misaligned-I/O fallback, vhost_scsi_revert_map_iov_to_sgl() puts pages already added to the SG list. The cleanup loop starts at pages[npages], but accounts for its first page as PAGE_SIZE bytes rather than PAGE_SIZE - offset. If the remaining data starts at a non-zero offset, it can finish one page early and leave a page reference behind. Use PAGE_SIZE - offset for the first remaining page and clear offset for later pages, as in the mapping loop. Without this, each affected request leaks one page reference. Fixes: bca939d5bcd0 ("vhost-scsi: Dynamically allocate scatterlists") Reviewed-by: Mike Christie Signed-off-by: Jia Jia Signed-off-by: Michael S. Tsirkin Message-ID: <20261023104035.6686-1-physicalmtea@gmail.com> --- drivers/vhost/scsi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 3fc7a115e8ab..e44044449cef 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -900,11 +900,16 @@ vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd, vhost_scsi_revert_map_iov_to_sgl(iter, *sgl, sg); iov_iter_revert(iter, bytes); + /* + * pages[npages] is the first page not added to the SG list. + * The remaining data starts at offset in that page. + */ while (bytes) { - n = min_t(unsigned int, PAGE_SIZE, bytes); + n = min_t(unsigned int, PAGE_SIZE - offset, bytes); put_page(pages[npages++]); bytes -= n; + offset = 0; } return -EINVAL;