Blame SOURCES/kvm-vhost-Track-descriptor-chain-in-private-at-SVQ.patch

586cba
From 486647551223cc01f4dba87197030bbf4e674f0f Mon Sep 17 00:00:00 2001
586cba
From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= <eperezma@redhat.com>
586cba
Date: Thu, 21 Jul 2022 15:24:48 +0200
586cba
Subject: [PATCH 01/32] vhost: Track descriptor chain in private at SVQ
586cba
MIME-Version: 1.0
586cba
Content-Type: text/plain; charset=UTF-8
586cba
Content-Transfer-Encoding: 8bit
586cba
586cba
RH-Author: Eugenio Pérez <eperezma@redhat.com>
586cba
RH-MergeRequest: 108: Net Control Virtqueue shadow Support
586cba
RH-Commit: [1/27] 26d16dc383e3064ac6e4288d5c52b39fee0ad204 (eperezmartin/qemu-kvm)
586cba
RH-Bugzilla: 1939363
586cba
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
586cba
RH-Acked-by: Cindy Lu <lulu@redhat.com>
586cba
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
586cba
586cba
Bugzilla: https://bugzilla.redhat.com/1939363
586cba
586cba
Upstream Status: git://git.qemu.org/qemu.git
586cba
586cba
commit 495fe3a78749c39c0e772c4e1a55d6cb8a7e5292
586cba
Author: Eugenio Pérez <eperezma@redhat.com>
586cba
Date:   Thu May 12 19:57:42 2022 +0200
586cba
586cba
    vhost: Track descriptor chain in private at SVQ
586cba
586cba
    The device could have access to modify them, and it definitely have
586cba
    access when we implement packed vq. Harden SVQ maintaining a private
586cba
    copy of the descriptor chain. Other fields like buffer addresses are
586cba
    already maintained sepparatedly.
586cba
586cba
    Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
586cba
    Message-Id: <20220512175747.142058-2-eperezma@redhat.com>
586cba
    Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
586cba
    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
586cba
586cba
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
586cba
---
586cba
 hw/virtio/vhost-shadow-virtqueue.c | 12 +++++++-----
586cba
 hw/virtio/vhost-shadow-virtqueue.h |  6 ++++++
586cba
 2 files changed, 13 insertions(+), 5 deletions(-)
586cba
586cba
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
586cba
index b232803d1b..3155801f50 100644
586cba
--- a/hw/virtio/vhost-shadow-virtqueue.c
586cba
+++ b/hw/virtio/vhost-shadow-virtqueue.c
586cba
@@ -138,6 +138,7 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
586cba
     for (n = 0; n < num; n++) {
586cba
         if (more_descs || (n + 1 < num)) {
586cba
             descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);
586cba
+            descs[i].next = cpu_to_le16(svq->desc_next[i]);
586cba
         } else {
586cba
             descs[i].flags = flags;
586cba
         }
586cba
@@ -145,10 +146,10 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
586cba
         descs[i].len = cpu_to_le32(iovec[n].iov_len);
586cba
 
586cba
         last = i;
586cba
-        i = cpu_to_le16(descs[i].next);
586cba
+        i = cpu_to_le16(svq->desc_next[i]);
586cba
     }
586cba
 
586cba
-    svq->free_head = le16_to_cpu(descs[last].next);
586cba
+    svq->free_head = le16_to_cpu(svq->desc_next[last]);
586cba
 }
586cba
 
586cba
 static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
586cba
@@ -336,7 +337,6 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq)
586cba
 static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
586cba
                                            uint32_t *len)
586cba
 {
586cba
-    vring_desc_t *descs = svq->vring.desc;
586cba
     const vring_used_t *used = svq->vring.used;
586cba
     vring_used_elem_t used_elem;
586cba
     uint16_t last_used;
586cba
@@ -365,7 +365,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
586cba
         return NULL;
586cba
     }
586cba
 
586cba
-    descs[used_elem.id].next = svq->free_head;
586cba
+    svq->desc_next[used_elem.id] = svq->free_head;
586cba
     svq->free_head = used_elem.id;
586cba
 
586cba
     *len = used_elem.len;
586cba
@@ -540,8 +540,9 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
586cba
     svq->vring.used = qemu_memalign(qemu_real_host_page_size, device_size);
586cba
     memset(svq->vring.used, 0, device_size);
586cba
     svq->ring_id_maps = g_new0(VirtQueueElement *, svq->vring.num);
586cba
+    svq->desc_next = g_new0(uint16_t, svq->vring.num);
586cba
     for (unsigned i = 0; i < svq->vring.num - 1; i++) {
586cba
-        svq->vring.desc[i].next = cpu_to_le16(i + 1);
586cba
+        svq->desc_next[i] = cpu_to_le16(i + 1);
586cba
     }
586cba
 }
586cba
 
586cba
@@ -574,6 +575,7 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
586cba
         virtqueue_detach_element(svq->vq, next_avail_elem, 0);
586cba
     }
586cba
     svq->vq = NULL;
586cba
+    g_free(svq->desc_next);
586cba
     g_free(svq->ring_id_maps);
586cba
     qemu_vfree(svq->vring.desc);
586cba
     qemu_vfree(svq->vring.used);
586cba
diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h
586cba
index e5e24c536d..c132c994e9 100644
586cba
--- a/hw/virtio/vhost-shadow-virtqueue.h
586cba
+++ b/hw/virtio/vhost-shadow-virtqueue.h
586cba
@@ -53,6 +53,12 @@ typedef struct VhostShadowVirtqueue {
586cba
     /* Next VirtQueue element that guest made available */
586cba
     VirtQueueElement *next_guest_avail_elem;
586cba
 
586cba
+    /*
586cba
+     * Backup next field for each descriptor so we can recover securely, not
586cba
+     * needing to trust the device access.
586cba
+     */
586cba
+    uint16_t *desc_next;
586cba
+
586cba
     /* Next head to expose to the device */
586cba
     uint16_t shadow_avail_idx;
586cba
 
586cba
-- 
586cba
2.31.1
586cba