All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Shadow VirtQueue Fixes
@ 2022-05-12 17:57 Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 1/6] vhost: Track descriptor chain in private at SVQ Eugenio Pérez
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Eugenio Pérez @ 2022-05-12 17:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Gautam Dawar, Laurent Vivier, Harpreet Singh Anand, qemu-stable,
	Philippe Mathieu-Daudé,
	Michael S. Tsirkin, Jason Wang, Gonglei (Arei),
	Cindy Lu

Random fixes found while developing control virtqueue + multiqueue but the last
one, found by coverity. The previous one is a patch created by Philippe
Mathieu-Daudé <f4bug@amsat.org>, send as a RFC in another series but already
acked.

All but Philippe's ones are bugs non-triggable, since there is still no
possibility to enable SVQ unless we manually add code to master.

Comments are welcome.

Eugenio Pérez (5):
  vhost: Track descriptor chain in private at SVQ
  vhost: Fix device's used descriptor dequeue
  vdpa: Fix bad index calculus at vhost_vdpa_get_vring_base
  vdpa: Fix index calculus at vhost_vdpa_svqs_start
  vhost: Fix element in vhost_svq_add failure

Philippe Mathieu-Daudé (1):
  hw/virtio: Replace g_memdup() by g_memdup2()

 hw/virtio/vhost-shadow-virtqueue.h |  6 +++++
 hw/net/virtio-net.c                |  3 ++-
 hw/virtio/vhost-shadow-virtqueue.c | 35 +++++++++++++++++++++++++-----
 hw/virtio/vhost-vdpa.c             |  6 ++---
 hw/virtio/virtio-crypto.c          |  6 ++---
 5 files changed, 43 insertions(+), 13 deletions(-)

--
2.27.0




^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/6] vhost: Track descriptor chain in private at SVQ
  2022-05-12 17:57 [PATCH 0/6] Shadow VirtQueue Fixes Eugenio Pérez
@ 2022-05-12 17:57 ` Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 2/6] vhost: Fix device's used descriptor dequeue Eugenio Pérez
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Eugenio Pérez @ 2022-05-12 17:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Gautam Dawar, Laurent Vivier, Harpreet Singh Anand, qemu-stable,
	Philippe Mathieu-Daudé,
	Michael S. Tsirkin, Jason Wang, Gonglei (Arei),
	Cindy Lu

The device could have access to modify them, and it definitely have
access when we implement packed vq. Harden SVQ maintaining a private
copy of the descriptor chain. Other fields like buffer addresses are
already maintained sepparatedly.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.h |  6 ++++++
 hw/virtio/vhost-shadow-virtqueue.c | 12 +++++++-----
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h
index e5e24c536d..c132c994e9 100644
--- a/hw/virtio/vhost-shadow-virtqueue.h
+++ b/hw/virtio/vhost-shadow-virtqueue.h
@@ -53,6 +53,12 @@ typedef struct VhostShadowVirtqueue {
     /* Next VirtQueue element that guest made available */
     VirtQueueElement *next_guest_avail_elem;

+    /*
+     * Backup next field for each descriptor so we can recover securely, not
+     * needing to trust the device access.
+     */
+    uint16_t *desc_next;
+
     /* Next head to expose to the device */
     uint16_t shadow_avail_idx;

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 1e5cfe2af6..1d6552b0fe 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -138,6 +138,7 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
     for (n = 0; n < num; n++) {
         if (more_descs || (n + 1 < num)) {
             descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);
+            descs[i].next = cpu_to_le16(svq->desc_next[i]);
         } else {
             descs[i].flags = flags;
         }
@@ -145,10 +146,10 @@ static void vhost_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
         descs[i].len = cpu_to_le32(iovec[n].iov_len);

         last = i;
-        i = cpu_to_le16(descs[i].next);
+        i = cpu_to_le16(svq->desc_next[i]);
     }

-    svq->free_head = le16_to_cpu(descs[last].next);
+    svq->free_head = le16_to_cpu(svq->desc_next[last]);
 }

 static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
@@ -336,7 +337,6 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq)
 static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
                                            uint32_t *len)
 {
-    vring_desc_t *descs = svq->vring.desc;
     const vring_used_t *used = svq->vring.used;
     vring_used_elem_t used_elem;
     uint16_t last_used;
@@ -365,7 +365,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
         return NULL;
     }

-    descs[used_elem.id].next = svq->free_head;
+    svq->desc_next[used_elem.id] = svq->free_head;
     svq->free_head = used_elem.id;

     *len = used_elem.len;
@@ -540,8 +540,9 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
     svq->vring.used = qemu_memalign(qemu_real_host_page_size(), device_size);
     memset(svq->vring.used, 0, device_size);
     svq->ring_id_maps = g_new0(VirtQueueElement *, svq->vring.num);
+    svq->desc_next = g_new0(uint16_t, svq->vring.num);
     for (unsigned i = 0; i < svq->vring.num - 1; i++) {
-        svq->vring.desc[i].next = cpu_to_le16(i + 1);
+        svq->desc_next[i] = cpu_to_le16(i + 1);
     }
 }

@@ -574,6 +575,7 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
         virtqueue_detach_element(svq->vq, next_avail_elem, 0);
     }
     svq->vq = NULL;
+    g_free(svq->desc_next);
     g_free(svq->ring_id_maps);
     qemu_vfree(svq->vring.desc);
     qemu_vfree(svq->vring.used);
--
2.27.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] vhost: Fix device's used descriptor dequeue
  2022-05-12 17:57 [PATCH 0/6] Shadow VirtQueue Fixes Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 1/6] vhost: Track descriptor chain in private at SVQ Eugenio Pérez
@ 2022-05-12 17:57 ` Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 3/6] vdpa: Fix bad index calculus at vhost_vdpa_get_vring_base Eugenio Pérez
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Eugenio Pérez @ 2022-05-12 17:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Gautam Dawar, Laurent Vivier, Harpreet Singh Anand, qemu-stable,
	Philippe Mathieu-Daudé,
	Michael S. Tsirkin, Jason Wang, Gonglei (Arei),
	Cindy Lu

Only the first one of them were properly enqueued back.

Fixes: 100890f7ca ("vhost: Shadow virtqueue buffers forwarding")

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 1d6552b0fe..a8376ef82b 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -334,12 +334,22 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq)
     svq->vring.avail->flags |= cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT);
 }
 
+static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
+                                             uint16_t num, uint16_t i)
+{
+    for (uint16_t j = 0; j < (num - 1); ++j) {
+        i = le16_to_cpu(svq->desc_next[i]);
+    }
+
+    return i;
+}
+
 static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
                                            uint32_t *len)
 {
     const vring_used_t *used = svq->vring.used;
     vring_used_elem_t used_elem;
-    uint16_t last_used;
+    uint16_t last_used, last_used_chain, num;
 
     if (!vhost_svq_more_used(svq)) {
         return NULL;
@@ -365,7 +375,10 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
         return NULL;
     }
 
-    svq->desc_next[used_elem.id] = svq->free_head;
+    num = svq->ring_id_maps[used_elem.id]->in_num +
+          svq->ring_id_maps[used_elem.id]->out_num;
+    last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
+    svq->desc_next[last_used_chain] = svq->free_head;
     svq->free_head = used_elem.id;
 
     *len = used_elem.len;
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] vdpa: Fix bad index calculus at vhost_vdpa_get_vring_base
  2022-05-12 17:57 [PATCH 0/6] Shadow VirtQueue Fixes Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 1/6] vhost: Track descriptor chain in private at SVQ Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 2/6] vhost: Fix device's used descriptor dequeue Eugenio Pérez
@ 2022-05-12 17:57 ` Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 4/6] vdpa: Fix index calculus at vhost_vdpa_svqs_start Eugenio Pérez
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Eugenio Pérez @ 2022-05-12 17:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Gautam Dawar, Laurent Vivier, Harpreet Singh Anand, qemu-stable,
	Philippe Mathieu-Daudé,
	Michael S. Tsirkin, Jason Wang, Gonglei (Arei),
	Cindy Lu

Fixes: 6d0b222666 ("vdpa: Adapt vhost_vdpa_get_vring_base to SVQ")

Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
 hw/virtio/vhost-vdpa.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index a30510ed17..493269b0b5 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1172,11 +1172,11 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev *dev,
                                        struct vhost_vring_state *ring)
 {
     struct vhost_vdpa *v = dev->opaque;
+    int vdpa_idx = ring->index - dev->vq_index;
     int ret;
 
     if (v->shadow_vqs_enabled) {
-        VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs,
-                                                      ring->index);
+        VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, vdpa_idx);
 
         /*
          * Setting base as last used idx, so destination will see as available
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] vdpa: Fix index calculus at vhost_vdpa_svqs_start
  2022-05-12 17:57 [PATCH 0/6] Shadow VirtQueue Fixes Eugenio Pérez
                   ` (2 preceding siblings ...)
  2022-05-12 17:57 ` [PATCH 3/6] vdpa: Fix bad index calculus at vhost_vdpa_get_vring_base Eugenio Pérez
@ 2022-05-12 17:57 ` Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 5/6] hw/virtio: Replace g_memdup() by g_memdup2() Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 6/6] vhost: Fix element in vhost_svq_add failure Eugenio Pérez
  5 siblings, 0 replies; 7+ messages in thread
From: Eugenio Pérez @ 2022-05-12 17:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Gautam Dawar, Laurent Vivier, Harpreet Singh Anand, qemu-stable,
	Philippe Mathieu-Daudé,
	Michael S. Tsirkin, Jason Wang, Gonglei (Arei),
	Cindy Lu

With the introduction of MQ the index of the vq needs to be calculated
with the device model vq_index.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
---
 hw/virtio/vhost-vdpa.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 493269b0b5..ed106bff47 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1018,7 +1018,7 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev)
         VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i);
         VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
         struct vhost_vring_addr addr = {
-            .index = i,
+            .index = dev->vq_index + i,
         };
         int r;
         bool ok = vhost_vdpa_svq_setup(dev, svq, i, &err);
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] hw/virtio: Replace g_memdup() by g_memdup2()
  2022-05-12 17:57 [PATCH 0/6] Shadow VirtQueue Fixes Eugenio Pérez
                   ` (3 preceding siblings ...)
  2022-05-12 17:57 ` [PATCH 4/6] vdpa: Fix index calculus at vhost_vdpa_svqs_start Eugenio Pérez
@ 2022-05-12 17:57 ` Eugenio Pérez
  2022-05-12 17:57 ` [PATCH 6/6] vhost: Fix element in vhost_svq_add failure Eugenio Pérez
  5 siblings, 0 replies; 7+ messages in thread
From: Eugenio Pérez @ 2022-05-12 17:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Gautam Dawar, Laurent Vivier, Harpreet Singh Anand, qemu-stable,
	Philippe Mathieu-Daudé,
	Michael S. Tsirkin, Jason Wang, Gonglei (Arei),
	Cindy Lu

From: Philippe Mathieu-Daudé <philmd@redhat.com>

Per https://discourse.gnome.org/t/port-your-module-from-g-memdup-to-g-memdup2-now/5538

  The old API took the size of the memory to duplicate as a guint,
  whereas most memory functions take memory sizes as a gsize. This
  made it easy to accidentally pass a gsize to g_memdup(). For large
  values, that would lead to a silent truncation of the size from 64
  to 32 bits, and result in a heap area being returned which is
  significantly smaller than what the caller expects. This can likely
  be exploited in various modules to cause a heap buffer overflow.

Replace g_memdup() by the safer g_memdup2() wrapper.

Acked-by: Jason Wang <jasowang@redhat.com>
Acked-by: Eugenio Pérez <eperezma@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/net/virtio-net.c       | 3 ++-
 hw/virtio/virtio-crypto.c | 6 +++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 1067e72b39..e4748a7e6c 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1443,7 +1443,8 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
         }
 
         iov_cnt = elem->out_num;
-        iov2 = iov = g_memdup(elem->out_sg, sizeof(struct iovec) * elem->out_num);
+        iov2 = iov = g_memdup2(elem->out_sg,
+                               sizeof(struct iovec) * elem->out_num);
         s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
         iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
         if (s != sizeof(ctrl)) {
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index dcd80b904d..0e31e3cc04 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -242,7 +242,7 @@ static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
         }
 
         out_num = elem->out_num;
-        out_iov_copy = g_memdup(elem->out_sg, sizeof(out_iov[0]) * out_num);
+        out_iov_copy = g_memdup2(elem->out_sg, sizeof(out_iov[0]) * out_num);
         out_iov = out_iov_copy;
 
         in_num = elem->in_num;
@@ -605,11 +605,11 @@ virtio_crypto_handle_request(VirtIOCryptoReq *request)
     }
 
     out_num = elem->out_num;
-    out_iov_copy = g_memdup(elem->out_sg, sizeof(out_iov[0]) * out_num);
+    out_iov_copy = g_memdup2(elem->out_sg, sizeof(out_iov[0]) * out_num);
     out_iov = out_iov_copy;
 
     in_num = elem->in_num;
-    in_iov_copy = g_memdup(elem->in_sg, sizeof(in_iov[0]) * in_num);
+    in_iov_copy = g_memdup2(elem->in_sg, sizeof(in_iov[0]) * in_num);
     in_iov = in_iov_copy;
 
     if (unlikely(iov_to_buf(out_iov, out_num, 0, &req, sizeof(req))
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] vhost: Fix element in vhost_svq_add failure
  2022-05-12 17:57 [PATCH 0/6] Shadow VirtQueue Fixes Eugenio Pérez
                   ` (4 preceding siblings ...)
  2022-05-12 17:57 ` [PATCH 5/6] hw/virtio: Replace g_memdup() by g_memdup2() Eugenio Pérez
@ 2022-05-12 17:57 ` Eugenio Pérez
  5 siblings, 0 replies; 7+ messages in thread
From: Eugenio Pérez @ 2022-05-12 17:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Gautam Dawar, Laurent Vivier, Harpreet Singh Anand, qemu-stable,
	Philippe Mathieu-Daudé,
	Michael S. Tsirkin, Jason Wang, Gonglei (Arei),
	Cindy Lu

Coverity rightly reports that is not free in that case.

Fixes: Coverity CID 1487559
Fixes: 100890f7ca ("vhost: Shadow virtqueue buffers forwarding")

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
 hw/virtio/vhost-shadow-virtqueue.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index a8376ef82b..56c96ebd13 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -199,11 +199,19 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
     return true;
 }
 
+/**
+ * Add an element to a SVQ.
+ *
+ * The caller must check that there is enough slots for the new element. It
+ * takes ownership of the element: In case of failure, it is free and the SVQ
+ * is considered broken.
+ */
 static bool vhost_svq_add(VhostShadowVirtqueue *svq, VirtQueueElement *elem)
 {
     unsigned qemu_head;
     bool ok = vhost_svq_add_split(svq, elem, &qemu_head);
     if (unlikely(!ok)) {
+        g_free(elem);
         return false;
     }
 
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-05-12 19:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-12 17:57 [PATCH 0/6] Shadow VirtQueue Fixes Eugenio Pérez
2022-05-12 17:57 ` [PATCH 1/6] vhost: Track descriptor chain in private at SVQ Eugenio Pérez
2022-05-12 17:57 ` [PATCH 2/6] vhost: Fix device's used descriptor dequeue Eugenio Pérez
2022-05-12 17:57 ` [PATCH 3/6] vdpa: Fix bad index calculus at vhost_vdpa_get_vring_base Eugenio Pérez
2022-05-12 17:57 ` [PATCH 4/6] vdpa: Fix index calculus at vhost_vdpa_svqs_start Eugenio Pérez
2022-05-12 17:57 ` [PATCH 5/6] hw/virtio: Replace g_memdup() by g_memdup2() Eugenio Pérez
2022-05-12 17:57 ` [PATCH 6/6] vhost: Fix element in vhost_svq_add failure Eugenio Pérez

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.