From: Li RongQing <[email protected]>

vhost_svq_next_desc checks id against vring.num before incrementing,
so when id == vring.num - 1 the function returns vring.num instead of
0.  This causes vhost_svq_vring_write_descs to write descs[num-1].next
= num (an invalid descriptor index) and, on the next iteration, to
access descs[num] — which lies past the descriptor ring and into the
avail ring, corrupting it.

The bug triggers whenever an IN_ORDER descriptor chain wraps around the
end of the SVQ ring.

Fix by incrementing id first, then checking for wrap-around.

Fixes: 485c9e69ef6e ("vhost: add in_order feature to shadow virtqueue")
Signed-off-by: Li RongQing <[email protected]>
---
 hw/virtio/vhost-shadow-virtqueue.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index 9404762..d4f5299 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -155,7 +155,7 @@ static uint16_t vhost_svq_next_desc(const 
VhostShadowVirtqueue *svq,
                                     uint16_t id)
 {
     if (virtio_vdev_has_feature(svq->vdev, VIRTIO_F_IN_ORDER)) {
-        return (id == svq->vring.num) ? 0 : ++id;
+        return (++id == svq->vring.num) ? 0 : id;
     } else {
         return svq->desc_state[id].next;
     }
-- 
2.9.4


Reply via email to