summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinfeng Sun <slf@hdu.edu.cn>2026-07-27 11:18:41 +0300
committerMichael S. Tsirkin <mst@redhat.com>2026-08-04 06:08:15 +0300
commitd876c493fc4b811941bfeb4c80beb2dfc4bf025e (patch)
treef86ce2cd54512e83a3aa0528c99560526caedb2d
parent727e1f569855df83579edbd73dcb4a0723543a12 (diff)
downloadlinux-d876c493fc4b811941bfeb4c80beb2dfc4bf025e.tar.xz
vhost-scsi: Validate T10 PI scatterlist counts
When T10 PI is negotiated, vhost-scsi splits protection bytes from the data iterator before mapping the request scatterlists. A malformed request can claim protection bytes that cover or exceed the full payload length. The former leaves no data bytes to map, while the latter underflows exp_data_len before advancing the iterator. Both cases can let a zero data SGL count reach sg_alloc_table_chained(), which triggers BUG_ON(!nents). Reject protection lengths that cover or exceed the payload before subtracting prot_bytes and advancing the iterator. Also propagate negative errors from the protection SGL calculation before calling the allocator, matching the data SGL path. Fixes: bca939d5bcd0 ("vhost-scsi: Dynamically allocate scatterlists") Suggested-by: Jia Jia <physicalmtea@gmail.com> Signed-off-by: Jia Jia <physicalmtea@gmail.com> Assisted-by: OpenAI-Codex:GPT-5 Signed-off-by: Linfeng Sun <linfeng.sun.dev@gmail.com> Message-ID: <20260727081841.923151-1-slf@hdu.edu.cn> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--drivers/vhost/scsi.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 9a1253b9d8c5..c79197edb163 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -972,6 +972,9 @@ vhost_scsi_mapal(struct vhost_scsi *vs, struct vhost_scsi_cmd *cmd,
if (prot_bytes) {
sgl_count = vhost_scsi_calc_sgls(prot_iter, prot_bytes,
VHOST_SCSI_PREALLOC_PROT_SGLS);
+ if (sgl_count < 0)
+ return sgl_count;
+
cmd->prot_table.sgl = cmd->prot_sgl;
ret = sg_alloc_table_chained(&cmd->prot_table, sgl_count,
cmd->prot_table.sgl,
@@ -1416,6 +1419,11 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
* actual data payload length.
*/
if (prot_bytes) {
+ if (prot_bytes >= exp_data_len) {
+ vq_err(vq, "Protection data exceeds payload length\n");
+ goto err;
+ }
+
exp_data_len -= prot_bytes;
prot_iter = data_iter;
iov_iter_truncate(&prot_iter, prot_bytes);