Skip to content

Commit 9ef41eb

Browse files
israelrumstsirkin
authored andcommitted
virtio-pci: Fix result size returned for the admin command completion
The result size returned by virtio_pci_admin_dev_parts_get() is 8 bytes larger than the actual result data size. This occurs because the result_sg_size field of the command is filled with the result length from virtqueue_get_buf(), which includes both the data size and an additional 8 bytes of status. This oversized result size causes two issues: 1. The state transferred to the destination includes 8 bytes of extra data at the end. 2. The allocated buffer in the kernel may be smaller than the returned size, leading to failures when reading beyond the allocated size. The commit fixes this by subtracting the status size from the result of virtqueue_get_buf(). This fix has been tested through live migrations with virtio-net, virtio-net-transitional, and virtio-blk devices. Fixes: 704806c ("virtio: Extend the admin command to include the result size") Signed-off-by: Israel Rukshin <israelr@nvidia.com> Reviewed-by: Parav Pandit <parav@nvidia.com> Reviewed-by: Max Gurtovoy <mgurtovoy@nvidia.com> Message-Id: <1745318025-23103-1-git-send-email-israelr@nvidia.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
1 parent eec8127 commit 9ef41eb

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

drivers/virtio/virtio_pci_modern.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ void vp_modern_avq_done(struct virtqueue *vq)
4848
{
4949
struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
5050
struct virtio_pci_admin_vq *admin_vq = &vp_dev->admin_vq;
51+
unsigned int status_size = sizeof(struct virtio_admin_cmd_status);
5152
struct virtio_admin_cmd *cmd;
5253
unsigned long flags;
5354
unsigned int len;
@@ -56,7 +57,17 @@ void vp_modern_avq_done(struct virtqueue *vq)
5657
do {
5758
virtqueue_disable_cb(vq);
5859
while ((cmd = virtqueue_get_buf(vq, &len))) {
59-
cmd->result_sg_size = len;
60+
/* If the number of bytes written by the device is less
61+
* than the size of struct virtio_admin_cmd_status, the
62+
* remaining status bytes will remain zero-initialized,
63+
* since the buffer was zeroed during allocation.
64+
* In this case, set the size of command_specific_result
65+
* to 0.
66+
*/
67+
if (len < status_size)
68+
cmd->result_sg_size = 0;
69+
else
70+
cmd->result_sg_size = len - status_size;
6071
complete(&cmd->completion);
6172
}
6273
} while (!virtqueue_enable_cb(vq));

0 commit comments

Comments
 (0)