[PATCH v3 6/7] hw/scsi/virtio-scsi: harden virtio_scsi_load_request() against invalid stream
Laurent Vivier <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu.stable,gmane.comp.emulators.qemu,gmane.comp.emulators.qemu.block |
|---|---|
| Message-ID | <[email protected]> |
virtio_scsi_load_request() uses assert() and exit(1) for conditions that can be triggered by a crafted migration stream: an out-of-range queue index, a malformed SCSI request, or a command mode mismatch. Replace these with proper error returns so the migration fails gracefully instead of aborting the destination QEMU process. Cc: [email protected] Fixes: 5db1764cc1f6 ("virtio-scsi: add migration support") Fixes: d2ad7dd46e72 ("virtio-scsi: add multiqueue capability") Fixes: 36b15c79aa1b ("virtio-scsi: start preparing for any_layout") Signed-off-by: Laurent Vivier <[email protected]> --- Notes: v2: add error_setg() calls with descriptive error messages for all three error paths hw/scsi/virtio-scsi.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 10eee3a4cff8..8814b246048f 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -272,7 +272,12 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq, uint32_t n; qemu_get_be32s(f, &n); - assert(n < vs->conf.num_queues); + if (n >= vs->conf.num_queues) { + error_setg(errp, "Invalid queues number %u > %u", n, + vs->conf.num_queues); + return NULL; + } + req = qemu_get_virtqueue_element(vdev, f, sizeof(VirtIOSCSIReq) + vs->cdb_size); if (!req) { @@ -283,14 +288,20 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq, if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size, sizeof(VirtIOSCSICmdResp) + vs->sense_size) < 0) { - error_report("invalid SCSI request migration data"); - exit(1); + error_setg(errp, "invalid SCSI request migration data"); + virtio_scsi_free_req(req); + return NULL; } scsi_req_ref(sreq); req->sreq = sreq; - if (req->sreq->cmd.mode != SCSI_XFER_NONE) { - assert(req->sreq->cmd.mode == req->mode); + if (req->sreq->cmd.mode != SCSI_XFER_NONE && + req->sreq->cmd.mode != req->mode) { + error_setg(errp, "Invalid SCSI request mode %u", + req->sreq->cmd.mode); + scsi_req_unref(sreq); + virtio_scsi_free_req(req); + return NULL; } return req; } -- 2.54.0