Blame SOURCES/0009-examples-vhost-move-to-safe-GPA-translation-API.patch

c7ffa4
From cbf70816520746639e6db436f356ba0cd36e0bb3 Mon Sep 17 00:00:00 2001
c7ffa4
From: Maxime Coquelin <maxime.coquelin@redhat.com>
c7ffa4
Date: Mon, 23 Apr 2018 11:33:46 +0200
c7ffa4
Subject: [PATCH 09/11] examples/vhost: move to safe GPA translation API
c7ffa4
c7ffa4
This patch uses the new rte_vhost_va_from_guest_pa() API
c7ffa4
to ensure the application doesn't perform out-of-bound
c7ffa4
accesses either because of a malicious guest providing an
c7ffa4
incorrect descriptor length, or because the buffer is
c7ffa4
contiguous in guest physical address space but not in the
c7ffa4
host process virtual address space.
c7ffa4
c7ffa4
This issue has been assigned CVE-2018-1059.
c7ffa4
c7ffa4
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
c7ffa4
---
c7ffa4
 examples/vhost/virtio_net.c | 94 +++++++++++++++++++++++++++++++++++++++------
c7ffa4
 1 file changed, 83 insertions(+), 11 deletions(-)
c7ffa4
c7ffa4
diff --git a/examples/vhost/virtio_net.c b/examples/vhost/virtio_net.c
c7ffa4
index 1ab57f5..31c3dd0 100644
c7ffa4
--- a/examples/vhost/virtio_net.c
c7ffa4
+++ b/examples/vhost/virtio_net.c
c7ffa4
@@ -86,8 +86,9 @@
c7ffa4
 {
c7ffa4
 	uint32_t desc_avail, desc_offset;
c7ffa4
+	uint64_t desc_chunck_len;
c7ffa4
 	uint32_t mbuf_avail, mbuf_offset;
c7ffa4
 	uint32_t cpy_len;
c7ffa4
 	struct vring_desc *desc;
c7ffa4
-	uint64_t desc_addr;
c7ffa4
+	uint64_t desc_addr, desc_gaddr;
c7ffa4
 	struct virtio_net_hdr virtio_hdr = {0, 0, 0, 0, 0, 0};
c7ffa4
 	/* A counter to avoid desc dead loop chain */
c7ffa4
@@ -95,5 +96,8 @@
c7ffa4
 
c7ffa4
 	desc = &vr->desc[desc_idx];
c7ffa4
-	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
c7ffa4
+	desc_chunck_len = desc->len;
c7ffa4
+	desc_gaddr = desc->addr;
c7ffa4
+	desc_addr = rte_vhost_va_from_guest_pa(
c7ffa4
+			dev->mem, desc_gaddr, &desc_chunck_len);
c7ffa4
 	/*
c7ffa4
 	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
c7ffa4
@@ -107,7 +111,40 @@
c7ffa4
 
c7ffa4
 	/* write virtio-net header */
c7ffa4
-	*(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr;
c7ffa4
+	if (likely(desc_chunck_len >= dev->hdr_len)) {
c7ffa4
+		*(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr;
c7ffa4
+		desc_offset = dev->hdr_len;
c7ffa4
+	} else {
c7ffa4
+		uint64_t len;
c7ffa4
+		uint64_t remain = dev->hdr_len;
c7ffa4
+		uint64_t src = (uint64_t)(uintptr_t)&virtio_hdr, dst;
c7ffa4
+		uint64_t guest_addr = desc_gaddr;
c7ffa4
+
c7ffa4
+		while (remain) {
c7ffa4
+			len = remain;
c7ffa4
+			dst = rte_vhost_va_from_guest_pa(dev->mem,
c7ffa4
+					guest_addr, &len;;
c7ffa4
+			if (unlikely(!dst || !len))
c7ffa4
+				return -1;
c7ffa4
+
c7ffa4
+			rte_memcpy((void *)(uintptr_t)dst,
c7ffa4
+					(void *)(uintptr_t)src,
c7ffa4
+					len);
c7ffa4
+
c7ffa4
+			remain -= len;
c7ffa4
+			guest_addr += len;
c7ffa4
+			dst += len;
c7ffa4
+		}
c7ffa4
+
c7ffa4
+		desc_chunck_len = desc->len - dev->hdr_len;
c7ffa4
+		desc_gaddr += dev->hdr_len;
c7ffa4
+		desc_addr = rte_vhost_va_from_guest_pa(
c7ffa4
+				dev->mem, desc_gaddr,
c7ffa4
+				&desc_chunck_len);
c7ffa4
+		if (unlikely(!desc_addr))
c7ffa4
+			return -1;
c7ffa4
+
c7ffa4
+		desc_offset = 0;
c7ffa4
+	}
c7ffa4
 
c7ffa4
-	desc_offset = dev->hdr_len;
c7ffa4
 	desc_avail  = desc->len - dev->hdr_len;
c7ffa4
 
c7ffa4
@@ -134,5 +171,8 @@
c7ffa4
 
c7ffa4
 			desc = &vr->desc[desc->next];
c7ffa4
-			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
c7ffa4
+			desc_chunck_len = desc->len;
c7ffa4
+			desc_gaddr = desc->addr;
c7ffa4
+			desc_addr = rte_vhost_va_from_guest_pa(
c7ffa4
+					dev->mem, desc_gaddr, &desc_chunck_len);
c7ffa4
 			if (unlikely(!desc_addr))
c7ffa4
 				return -1;
c7ffa4
@@ -140,7 +180,17 @@
c7ffa4
 			desc_offset = 0;
c7ffa4
 			desc_avail  = desc->len;
c7ffa4
+		} else if (unlikely(desc_chunck_len == 0)) {
c7ffa4
+			desc_chunck_len = desc_avail;
c7ffa4
+			desc_gaddr += desc_offset;
c7ffa4
+			desc_addr = rte_vhost_va_from_guest_pa(dev->mem,
c7ffa4
+					desc_gaddr,
c7ffa4
+					&desc_chunck_len);
c7ffa4
+			if (unlikely(!desc_addr))
c7ffa4
+				return -1;
c7ffa4
+
c7ffa4
+			desc_offset = 0;
c7ffa4
 		}
c7ffa4
 
c7ffa4
-		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
c7ffa4
+		cpy_len = RTE_MIN(desc_chunck_len, mbuf_avail);
c7ffa4
 		rte_memcpy((void *)((uintptr_t)(desc_addr + desc_offset)),
c7ffa4
 			rte_pktmbuf_mtod_offset(m, void *, mbuf_offset),
c7ffa4
@@ -151,4 +201,5 @@
c7ffa4
 		desc_avail  -= cpy_len;
c7ffa4
 		desc_offset += cpy_len;
c7ffa4
+		desc_chunck_len -= cpy_len;
c7ffa4
 	}
c7ffa4
 
c7ffa4
@@ -224,6 +275,7 @@
c7ffa4
 {
c7ffa4
 	struct vring_desc *desc;
c7ffa4
-	uint64_t desc_addr;
c7ffa4
+	uint64_t desc_addr, desc_gaddr;
c7ffa4
 	uint32_t desc_avail, desc_offset;
c7ffa4
+	uint64_t desc_chunck_len;
c7ffa4
 	uint32_t mbuf_avail, mbuf_offset;
c7ffa4
 	uint32_t cpy_len;
c7ffa4
@@ -237,5 +289,8 @@
c7ffa4
 		return -1;
c7ffa4
 
c7ffa4
-	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
c7ffa4
+	desc_chunck_len = desc->len;
c7ffa4
+	desc_gaddr = desc->addr;
c7ffa4
+	desc_addr = rte_vhost_va_from_guest_pa(
c7ffa4
+			dev->mem, desc_gaddr, &desc_chunck_len);
c7ffa4
 	if (unlikely(!desc_addr))
c7ffa4
 		return -1;
c7ffa4
@@ -251,5 +306,8 @@
c7ffa4
 	 */
c7ffa4
 	desc = &vr->desc[desc->next];
c7ffa4
-	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
c7ffa4
+	desc_chunck_len = desc->len;
c7ffa4
+	desc_gaddr = desc->addr;
c7ffa4
+	desc_addr = rte_vhost_va_from_guest_pa(
c7ffa4
+			dev->mem, desc_gaddr, &desc_chunck_len);
c7ffa4
 	if (unlikely(!desc_addr))
c7ffa4
 		return -1;
c7ffa4
@@ -263,5 +321,5 @@
c7ffa4
 	mbuf_avail  = m->buf_len - RTE_PKTMBUF_HEADROOM;
c7ffa4
 	while (1) {
c7ffa4
-		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
c7ffa4
+		cpy_len = RTE_MIN(desc_chunck_len, mbuf_avail);
c7ffa4
 		rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *,
c7ffa4
 						   mbuf_offset),
c7ffa4
@@ -273,4 +331,5 @@
c7ffa4
 		desc_avail  -= cpy_len;
c7ffa4
 		desc_offset += cpy_len;
c7ffa4
+		desc_chunck_len -= cpy_len;
c7ffa4
 
c7ffa4
 		/* This desc reaches to its end, get the next one */
c7ffa4
@@ -284,5 +343,8 @@
c7ffa4
 			desc = &vr->desc[desc->next];
c7ffa4
 
c7ffa4
-			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
c7ffa4
+			desc_chunck_len = desc->len;
c7ffa4
+			desc_gaddr = desc->addr;
c7ffa4
+			desc_addr = rte_vhost_va_from_guest_pa(
c7ffa4
+					dev->mem, desc_gaddr, &desc_chunck_len);
c7ffa4
 			if (unlikely(!desc_addr))
c7ffa4
 				return -1;
c7ffa4
@@ -291,4 +353,14 @@
c7ffa4
 			desc_offset = 0;
c7ffa4
 			desc_avail  = desc->len;
c7ffa4
+		} else if (unlikely(desc_chunck_len == 0)) {
c7ffa4
+			desc_chunck_len = desc_avail;
c7ffa4
+			desc_gaddr += desc_offset;
c7ffa4
+			desc_addr = rte_vhost_va_from_guest_pa(dev->mem,
c7ffa4
+					desc_gaddr,
c7ffa4
+					&desc_chunck_len);
c7ffa4
+			if (unlikely(!desc_addr))
c7ffa4
+				return -1;
c7ffa4
+
c7ffa4
+			desc_offset = 0;
c7ffa4
 		}
c7ffa4
 
c7ffa4
-- 
c7ffa4
1.8.3.1
c7ffa4