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: bca939d5bc ("vhost-scsi: Dynamically allocate scatterlists")
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Jia Jia <physicalmtea@gmail.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20261023104035.6686-1-physicalmtea@gmail.com>
This commit is contained in:
Jia Jia 2026-10-23 18:40:35 +08:00 committed by Michael S. Tsirkin
parent bb2e6f1665
commit 058fc59326

View File

@ -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;