File 0296-virtio-make-sure-vdev-vq-i-.inuse-n.patch of Package qemu.10254

From eaeb373fc1ffec83426bf2c0d92e243433827e5d Mon Sep 17 00:00:00 2001
From: Fei Li <fli@suse.com>
Date: Thu, 15 Mar 2018 16:56:11 +0800
Subject: [PATCH] virtio: make sure vdev->vq[i].inuse never goes below 0

Set vdev->vq[i].inuse to 0 if its value goes below 0. Or else its
value would turn to be a large unsigned integer like 65535 when
comparing with unsigned vdev->vq[i].vring.num, which leads to an
error.

[FL: BSC#1020928]
Signed-off-by: Fei Li <fli@suse.com>
---
 hw/virtio/virtio.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 4738e33e1a..812e200895 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1097,6 +1097,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
     for (i = 0; i < num; i++) {
         if (vdev->vq[i].pa) {
             uint16_t nheads;
+            int inuse_tmp;
             nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
             /* Check it isn't doing strange things with descriptor numbers. */
             if (nheads > vdev->vq[i].vring.num) {
@@ -1115,8 +1116,17 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
              * Since max ring size < UINT16_MAX it's safe to use modulo
              * UINT16_MAX + 1 subtraction.
              */
-            vdev->vq[i].inuse = (uint16_t)(vdev->vq[i].last_avail_idx -
-                                vdev->vq[i].used_idx);
+            inuse_tmp = (int)(vdev->vq[i].last_avail_idx -
+                              vdev->vq[i].used_idx);
+            if (inuse_tmp < 0) {
+                printf("WARNING: for VQ %d, its last_avail_idx 0x%x < used_idx "
+                       "0x%x. Their difference will falsely turn to be a large "
+                       "unsigned integer like 65535 when later comparing with "
+                       "the unsigned vring.num. Set the minus to 0 to avoid.\n",
+                       i, vdev->vq[i].last_avail_idx, vdev->vq[i].used_idx);
+            }
+            vdev->vq[i].inuse = (inuse_tmp < 0 ? 0 : inuse_tmp);
+
             if (vdev->vq[i].inuse > vdev->vq[i].vring.num) {
                 error_report("VQ %d size 0x%x < last_avail_idx 0x%x - "
                              "used_idx 0x%x",
openSUSE Build Service is sponsored by