|
|
a6040a |
From 9fc3d1245bec49e29013b8120340e87adeaaf11a Mon Sep 17 00:00:00 2001
|
|
|
a6040a |
From: Maxime Coquelin <maxime.coquelin@redhat.com>
|
|
|
a6040a |
Date: Mon, 23 Apr 2018 11:33:42 +0200
|
|
|
a6040a |
Subject: [PATCH 05/11] vhost: add support for non-contiguous indirect descs
|
|
|
a6040a |
tables
|
|
|
a6040a |
|
|
|
a6040a |
This patch adds support for non-contiguous indirect descriptor
|
|
|
a6040a |
tables in VA space.
|
|
|
a6040a |
|
|
|
a6040a |
When it happens, which is unlikely, a table is allocated and the
|
|
|
a6040a |
non-contiguous content is copied into it.
|
|
|
a6040a |
|
|
|
a6040a |
This issue has been assigned CVE-2018-1059.
|
|
|
a6040a |
|
|
|
a6040a |
Reported-by: Yongji Xie <xieyongji@baidu.com>
|
|
|
a6040a |
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
|
|
|
a6040a |
---
|
|
|
a6040a |
lib/librte_vhost/virtio_net.c | 108 +++++++++++++++++++++++++++++++++++++++---
|
|
|
a6040a |
1 file changed, 101 insertions(+), 7 deletions(-)
|
|
|
a6040a |
|
|
|
a6040a |
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
|
|
|
a6040a |
index 79bac59..13252e6 100644
|
|
|
a6040a |
--- a/lib/librte_vhost/virtio_net.c
|
|
|
a6040a |
+++ b/lib/librte_vhost/virtio_net.c
|
|
|
a6040a |
@@ -46,4 +46,5 @@
|
|
|
a6040a |
#include <rte_arp.h>
|
|
|
a6040a |
#include <rte_spinlock.h>
|
|
|
a6040a |
+#include <rte_malloc.h>
|
|
|
a6040a |
|
|
|
a6040a |
#include "iotlb.h"
|
|
|
a6040a |
@@ -60,4 +61,44 @@
|
|
|
a6040a |
}
|
|
|
a6040a |
|
|
|
a6040a |
+static __rte_always_inline struct vring_desc *
|
|
|
a6040a |
+alloc_copy_ind_table(struct virtio_net *dev, struct vhost_virtqueue *vq,
|
|
|
a6040a |
+ struct vring_desc *desc)
|
|
|
a6040a |
+{
|
|
|
a6040a |
+ struct vring_desc *idesc;
|
|
|
a6040a |
+ uint64_t src, dst;
|
|
|
a6040a |
+ uint64_t len, remain = desc->len;
|
|
|
a6040a |
+ uint64_t desc_addr = desc->addr;
|
|
|
a6040a |
+
|
|
|
a6040a |
+ idesc = rte_malloc(__func__, desc->len, 0);
|
|
|
a6040a |
+ if (unlikely(!idesc))
|
|
|
a6040a |
+ return 0;
|
|
|
a6040a |
+
|
|
|
a6040a |
+ dst = (uint64_t)(uintptr_t)idesc;
|
|
|
a6040a |
+
|
|
|
a6040a |
+ while (remain) {
|
|
|
a6040a |
+ len = remain;
|
|
|
a6040a |
+ src = vhost_iova_to_vva(dev, vq, desc_addr, &len,
|
|
|
a6040a |
+ VHOST_ACCESS_RO);
|
|
|
a6040a |
+ if (unlikely(!src || !len)) {
|
|
|
a6040a |
+ rte_free(idesc);
|
|
|
a6040a |
+ return 0;
|
|
|
a6040a |
+ }
|
|
|
a6040a |
+
|
|
|
a6040a |
+ rte_memcpy((void *)(uintptr_t)dst, (void *)(uintptr_t)src, len);
|
|
|
a6040a |
+
|
|
|
a6040a |
+ remain -= len;
|
|
|
a6040a |
+ dst += len;
|
|
|
a6040a |
+ desc_addr += len;
|
|
|
a6040a |
+ }
|
|
|
a6040a |
+
|
|
|
a6040a |
+ return idesc;
|
|
|
a6040a |
+}
|
|
|
a6040a |
+
|
|
|
a6040a |
+static __rte_always_inline void
|
|
|
a6040a |
+free_ind_table(struct vring_desc *idesc)
|
|
|
a6040a |
+{
|
|
|
a6040a |
+ rte_free(idesc);
|
|
|
a6040a |
+}
|
|
|
a6040a |
+
|
|
|
a6040a |
static __rte_always_inline void
|
|
|
a6040a |
do_flush_shadow_used_ring(struct virtio_net *dev, struct vhost_virtqueue *vq,
|
|
|
a6040a |
@@ -376,4 +417,5 @@
|
|
|
a6040a |
rte_prefetch0(&vq->desc[desc_indexes[0]]);
|
|
|
a6040a |
for (i = 0; i < count; i++) {
|
|
|
a6040a |
+ struct vring_desc *idesc = NULL;
|
|
|
a6040a |
uint16_t desc_idx = desc_indexes[i];
|
|
|
a6040a |
int err;
|
|
|
a6040a |
@@ -385,10 +427,22 @@
|
|
|
a6040a |
vq, vq->desc[desc_idx].addr,
|
|
|
a6040a |
&dlen, VHOST_ACCESS_RO);
|
|
|
a6040a |
- if (unlikely(!descs ||
|
|
|
a6040a |
- dlen != vq->desc[desc_idx].len)) {
|
|
|
a6040a |
+ if (unlikely(!descs)) {
|
|
|
a6040a |
count = i;
|
|
|
a6040a |
break;
|
|
|
a6040a |
}
|
|
|
a6040a |
|
|
|
a6040a |
+ if (unlikely(dlen < vq->desc[desc_idx].len)) {
|
|
|
a6040a |
+ /*
|
|
|
a6040a |
+ * The indirect desc table is not contiguous
|
|
|
a6040a |
+ * in process VA space, we have to copy it.
|
|
|
a6040a |
+ */
|
|
|
a6040a |
+ idesc = alloc_copy_ind_table(dev, vq,
|
|
|
a6040a |
+ &vq->desc[desc_idx]);
|
|
|
a6040a |
+ if (unlikely(!idesc))
|
|
|
a6040a |
+ break;
|
|
|
a6040a |
+
|
|
|
a6040a |
+ descs = idesc;
|
|
|
a6040a |
+ }
|
|
|
a6040a |
+
|
|
|
a6040a |
desc_idx = 0;
|
|
|
a6040a |
sz = vq->desc[desc_idx].len / sizeof(*descs);
|
|
|
a6040a |
@@ -401,4 +455,5 @@
|
|
|
a6040a |
if (unlikely(err)) {
|
|
|
a6040a |
count = i;
|
|
|
a6040a |
+ free_ind_table(idesc);
|
|
|
a6040a |
break;
|
|
|
a6040a |
}
|
|
|
a6040a |
@@ -406,4 +461,7 @@
|
|
|
a6040a |
if (i + 1 < count)
|
|
|
a6040a |
rte_prefetch0(&vq->desc[desc_indexes[i+1]]);
|
|
|
a6040a |
+
|
|
|
a6040a |
+ if (unlikely(!!idesc))
|
|
|
a6040a |
+ free_ind_table(idesc);
|
|
|
a6040a |
}
|
|
|
a6040a |
|
|
|
a6040a |
@@ -446,4 +504,5 @@
|
|
|
a6040a |
uint64_t dlen;
|
|
|
a6040a |
struct vring_desc *descs = vq->desc;
|
|
|
a6040a |
+ struct vring_desc *idesc = NULL;
|
|
|
a6040a |
|
|
|
a6040a |
*desc_chain_head = idx;
|
|
|
a6040a |
@@ -455,13 +514,27 @@
|
|
|
a6040a |
&dlen,
|
|
|
a6040a |
VHOST_ACCESS_RO);
|
|
|
a6040a |
- if (unlikely(!descs || dlen != vq->desc[idx].len))
|
|
|
a6040a |
+ if (unlikely(!descs))
|
|
|
a6040a |
return -1;
|
|
|
a6040a |
|
|
|
a6040a |
+ if (unlikely(dlen < vq->desc[idx].len)) {
|
|
|
a6040a |
+ /*
|
|
|
a6040a |
+ * The indirect desc table is not contiguous
|
|
|
a6040a |
+ * in process VA space, we have to copy it.
|
|
|
a6040a |
+ */
|
|
|
a6040a |
+ idesc = alloc_copy_ind_table(dev, vq, &vq->desc[idx]);
|
|
|
a6040a |
+ if (unlikely(!idesc))
|
|
|
a6040a |
+ return -1;
|
|
|
a6040a |
+
|
|
|
a6040a |
+ descs = idesc;
|
|
|
a6040a |
+ }
|
|
|
a6040a |
+
|
|
|
a6040a |
idx = 0;
|
|
|
a6040a |
}
|
|
|
a6040a |
|
|
|
a6040a |
while (1) {
|
|
|
a6040a |
- if (unlikely(vec_id >= BUF_VECTOR_MAX || idx >= vq->size))
|
|
|
a6040a |
+ if (unlikely(vec_id >= BUF_VECTOR_MAX || idx >= vq->size)) {
|
|
|
a6040a |
+ free_ind_table(idesc);
|
|
|
a6040a |
return -1;
|
|
|
a6040a |
+ }
|
|
|
a6040a |
|
|
|
a6040a |
len += descs[idx].len;
|
|
|
a6040a |
@@ -480,4 +553,7 @@
|
|
|
a6040a |
*vec_idx = vec_id;
|
|
|
a6040a |
|
|
|
a6040a |
+ if (unlikely(!!idesc))
|
|
|
a6040a |
+ free_ind_table(idesc);
|
|
|
a6040a |
+
|
|
|
a6040a |
return 0;
|
|
|
a6040a |
}
|
|
|
a6040a |
@@ -1333,5 +1409,5 @@
|
|
|
a6040a |
rte_prefetch0(&vq->desc[desc_indexes[0]]);
|
|
|
a6040a |
for (i = 0; i < count; i++) {
|
|
|
a6040a |
- struct vring_desc *desc;
|
|
|
a6040a |
+ struct vring_desc *desc, *idesc = NULL;
|
|
|
a6040a |
uint16_t sz, idx;
|
|
|
a6040a |
uint64_t dlen;
|
|
|
a6040a |
@@ -1348,8 +1424,20 @@
|
|
|
a6040a |
&dlen,
|
|
|
a6040a |
VHOST_ACCESS_RO);
|
|
|
a6040a |
- if (unlikely(!desc ||
|
|
|
a6040a |
- dlen != vq->desc[desc_indexes[i]].len))
|
|
|
a6040a |
+ if (unlikely(!desc))
|
|
|
a6040a |
break;
|
|
|
a6040a |
|
|
|
a6040a |
+ if (unlikely(dlen < vq->desc[desc_indexes[i]].len)) {
|
|
|
a6040a |
+ /*
|
|
|
a6040a |
+ * The indirect desc table is not contiguous
|
|
|
a6040a |
+ * in process VA space, we have to copy it.
|
|
|
a6040a |
+ */
|
|
|
a6040a |
+ idesc = alloc_copy_ind_table(dev, vq,
|
|
|
a6040a |
+ &vq->desc[desc_indexes[i]]);
|
|
|
a6040a |
+ if (unlikely(!idesc))
|
|
|
a6040a |
+ break;
|
|
|
a6040a |
+
|
|
|
a6040a |
+ desc = idesc;
|
|
|
a6040a |
+ }
|
|
|
a6040a |
+
|
|
|
a6040a |
rte_prefetch0(desc);
|
|
|
a6040a |
sz = vq->desc[desc_indexes[i]].len / sizeof(*desc);
|
|
|
a6040a |
@@ -1365,4 +1453,5 @@
|
|
|
a6040a |
RTE_LOG(ERR, VHOST_DATA,
|
|
|
a6040a |
"Failed to allocate memory for mbuf.\n");
|
|
|
a6040a |
+ free_ind_table(idesc);
|
|
|
a6040a |
break;
|
|
|
a6040a |
}
|
|
|
a6040a |
@@ -1372,4 +1461,5 @@
|
|
|
a6040a |
if (unlikely(err)) {
|
|
|
a6040a |
rte_pktmbuf_free(pkts[i]);
|
|
|
a6040a |
+ free_ind_table(idesc);
|
|
|
a6040a |
break;
|
|
|
a6040a |
}
|
|
|
a6040a |
@@ -1381,4 +1471,5 @@
|
|
|
a6040a |
if (!zmbuf) {
|
|
|
a6040a |
rte_pktmbuf_free(pkts[i]);
|
|
|
a6040a |
+ free_ind_table(idesc);
|
|
|
a6040a |
break;
|
|
|
a6040a |
}
|
|
|
a6040a |
@@ -1397,4 +1488,7 @@
|
|
|
a6040a |
TAILQ_INSERT_TAIL(&vq->zmbuf_list, zmbuf, next);
|
|
|
a6040a |
}
|
|
|
a6040a |
+
|
|
|
a6040a |
+ if (unlikely(!!idesc))
|
|
|
a6040a |
+ free_ind_table(idesc);
|
|
|
a6040a |
}
|
|
|
a6040a |
vq->last_avail_idx += i;
|
|
|
a6040a |
--
|
|
|
a6040a |
1.8.3.1
|
|
|
a6040a |
|