Blame SOURCES/0001-vhost-discard-too-small-descriptor-chains.patch

2b1ecb
From f167022606b5ccca27a627ae599538ce2348ef67 Mon Sep 17 00:00:00 2001
2b1ecb
Message-Id: <f167022606b5ccca27a627ae599538ce2348ef67.1666780268.git.tredaelli@redhat.com>
2b1ecb
From: Maxime Coquelin <maxime.coquelin@redhat.com>
2b1ecb
Date: Thu, 16 Jun 2022 11:35:56 +0200
2b1ecb
Subject: [PATCH 1/2] vhost: discard too small descriptor chains
2b1ecb
2b1ecb
[ upstream commit 71bd0cc536ad6d84188d947d6f24c17400d8f623 ]
2b1ecb
2b1ecb
This patch discards descriptor chains which are smaller
2b1ecb
than the Virtio-net header size, and ones that are equal.
2b1ecb
2b1ecb
Indeed, such descriptor chains sizes mean there is no
2b1ecb
packet data.
2b1ecb
2b1ecb
This patch also has the advantage of requesting the exact
2b1ecb
packets sizes for the mbufs.
2b1ecb
2b1ecb
CVE-2022-2132
2b1ecb
Fixes: 62250c1d0978 ("vhost: extract split ring handling from Rx and Tx functions")
2b1ecb
Fixes: c3ff0ac70acb ("vhost: improve performance by supporting large buffer")
2b1ecb
Fixes: 84d5204310d7 ("vhost: support async dequeue for split ring")
2b1ecb
2b1ecb
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
2b1ecb
Acked-by: Chenbo Xia <chenbo.xia@intel.com>
2b1ecb
Reviewed-by: David Marchand <david.marchand@redhat.com>
2b1ecb
---
2b1ecb
 lib/vhost/virtio_net.c | 21 +++++++++++++++++----
2b1ecb
 1 file changed, 17 insertions(+), 4 deletions(-)
2b1ecb
2b1ecb
diff --git a/lib/vhost/virtio_net.c b/lib/vhost/virtio_net.c
2b1ecb
index 858187d1b0..991a7a2bd4 100644
2b1ecb
--- a/lib/vhost/virtio_net.c
2b1ecb
+++ b/lib/vhost/virtio_net.c
2b1ecb
@@ -2334,10 +2334,10 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct vhost_virtqueue *vq,
2b1ecb
 	buf_addr = buf_vec[vec_idx].buf_addr;
2b1ecb
 	buf_len = buf_vec[vec_idx].buf_len;
2b1ecb
 
2b1ecb
-	if (unlikely(buf_len < dev->vhost_hlen && nr_vec <= 1)) {
2b1ecb
-		error = -1;
2b1ecb
-		goto out;
2b1ecb
-	}
2b1ecb
+	/*
2b1ecb
+	 * The caller has checked the descriptors chain is larger than the
2b1ecb
+	 * header size.
2b1ecb
+	 */
2b1ecb
 
2b1ecb
 	if (virtio_net_with_host_offload(dev)) {
2b1ecb
 		if (unlikely(buf_len < sizeof(struct virtio_net_hdr))) {
2b1ecb
@@ -2568,6 +2568,14 @@ virtio_dev_tx_split(struct virtio_net *dev, struct vhost_virtqueue *vq,
2b1ecb
 
2b1ecb
 		update_shadow_used_ring_split(vq, head_idx, 0);
2b1ecb
 
2b1ecb
+		if (unlikely(buf_len <= dev->vhost_hlen)) {
2b1ecb
+			dropped += 1;
2b1ecb
+			i++;
2b1ecb
+			break;
2b1ecb
+		}
2b1ecb
+
2b1ecb
+		buf_len -= dev->vhost_hlen;
2b1ecb
+
2b1ecb
 		err = virtio_dev_pktmbuf_prep(dev, pkts[i], buf_len);
2b1ecb
 		if (unlikely(err)) {
2b1ecb
 			/*
2b1ecb
@@ -2771,6 +2779,11 @@ vhost_dequeue_single_packed(struct virtio_net *dev,
2b1ecb
 					 VHOST_ACCESS_RO) < 0))
2b1ecb
 		return -1;
2b1ecb
 
2b1ecb
+	if (unlikely(buf_len <= dev->vhost_hlen))
2b1ecb
+		return -1;
2b1ecb
+
2b1ecb
+	buf_len -= dev->vhost_hlen;
2b1ecb
+
2b1ecb
 	if (unlikely(virtio_dev_pktmbuf_prep(dev, pkts, buf_len))) {
2b1ecb
 		if (!allocerr_warned) {
2b1ecb
 			VHOST_LOG_DATA(ERR,
2b1ecb
-- 
2b1ecb
2.37.3
2b1ecb