From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <stable-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id DE477A0C47
	for <public@inbox.dpdk.org>; Mon, 26 Jul 2021 15:54:40 +0200 (CEST)
Received: from [217.70.189.124] (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id D89EB40F35;
	Mon, 26 Jul 2021 15:54:40 +0200 (CEST)
Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com
 [209.85.128.44]) by mails.dpdk.org (Postfix) with ESMTP id BC889410F0
 for <stable@dpdk.org>; Mon, 26 Jul 2021 15:54:37 +0200 (CEST)
Received: by mail-wm1-f44.google.com with SMTP id
 k14-20020a05600c1c8eb02901f13dd1672aso54042wms.0
 for <stable@dpdk.org>; Mon, 26 Jul 2021 06:54:37 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;
 h=from:to:cc:subject:date:message-id:in-reply-to:references
 :mime-version:content-transfer-encoding;
 bh=tW5fc8AJbkdtWYmq0IZggBugmWaKhCnGOa+oAeRvDuM=;
 b=K+MiatabYt/ydapBAU7H3re1KbR3BB1kTJO6mCTNkIOqR+VM3qzBqGA55NDcdCfQWY
 UURgR3Fl8TaxRtzebRtjQJhtsGTzzAt128SZWjMWUmdYA5xklDXjfIyUSiRZLLp82WoW
 CsGl9CsRKOTc1z6dviqO2T69ca9titCJKcMGfnRp4nOHbFsoDGeOlc0IZqUOTQEdf3RT
 h7eZ82RW5UJoFKALKk/lCw62+0EJK4OzMwWveXYg53Pud5uZZ+MRi6sGWdJH1IKBOCRF
 yE0gG7CGVXDdc/L/hbHssPRWPQt2Zwb52RVIOe1+w1hWNySc0suW4/1lRcw4PR/9pAQt
 ZfqA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20161025;
 h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
 :references:mime-version:content-transfer-encoding;
 bh=tW5fc8AJbkdtWYmq0IZggBugmWaKhCnGOa+oAeRvDuM=;
 b=THYv/FD5S9zRyzQdWI3vlqCB1eGpx0tq/oJva6pGt8IPhSAEmdbWiwHTpVI10C4sdx
 O4/K1krrEevzzoDHhrTRLhYtrEuM97DIEhZiMCJhvJBmEkD7OkhdJu13rb50g91oo8Lj
 dhGN29ZxLIOt+nhMjQjXaI4ZHPRp7MqyYe6THebkxNgLJOgqzW+B7wRuSdM99W5pvnF2
 eRkcAVQSd559Ne9p/y48J+T5drUecnfybvDLldSgRLyYkMrQAA9FQySKE0LPkt1g3XI2
 5GgwQYRQ3BL3QLx1RQt/V82TOuoLuN1ANcJpow/uZY6YYQ35rSZlhO4krPMCWKk7FDGk
 vyJg==
X-Gm-Message-State: AOAM532bJuKW+XisvcSsnsXrHhuLE/DgcvINpsk0duW164X7/oEIC9ww
 pTRbcW2F5RtDrKnIjkAJzls=
X-Google-Smtp-Source: ABdhPJwNcfkDXOXpS0ui2lQMohV5umsZkz0omOJQcFcjGnrhbSCpopIA9/DTjLNtWlUPW+HRZF6K+w==
X-Received: by 2002:a1c:9851:: with SMTP id a78mr1260034wme.123.1627307677496; 
 Mon, 26 Jul 2021 06:54:37 -0700 (PDT)
Received: from localhost ([137.220.125.106])
 by smtp.gmail.com with ESMTPSA id n5sm41321856wri.31.2021.07.26.06.54.36
 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
 Mon, 26 Jul 2021 06:54:37 -0700 (PDT)
From: luca.boccassi@gmail.com
To: Xiao Wang <xiao.w.wang@intel.com>
Cc: Maxime Coquelin <maxime.coquelin@redhat.com>, dpdk stable <stable@dpdk.org>
Date: Mon, 26 Jul 2021 14:52:45 +0100
Message-Id: <20210726135322.149850-22-luca.boccassi@gmail.com>
X-Mailer: git-send-email 2.30.2
In-Reply-To: <20210726135322.149850-1-luca.boccassi@gmail.com>
References: <20210712130551.2462159-1-luca.boccassi@gmail.com>
 <20210726135322.149850-1-luca.boccassi@gmail.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Subject: [dpdk-stable] patch 'vhost: check header for legacy dequeue
 offload' has been queued to stable release 20.11.3
X-BeenThere: stable@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: patches for DPDK stable branches <stable.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/stable>,
 <mailto:stable-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/stable/>
List-Post: <mailto:stable@dpdk.org>
List-Help: <mailto:stable-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/stable>,
 <mailto:stable-request@dpdk.org?subject=subscribe>
Errors-To: stable-bounces@dpdk.org
Sender: "stable" <stable-bounces@dpdk.org>

Hi,

FYI, your patch has been queued to stable release 20.11.3

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 07/28/21. So please
shout if anyone has objections.

Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.

Queued patches are on a temporary branch at:
https://github.com/bluca/dpdk-stable

This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/2df90802c6f7cd84fa91ba3552d31c2fc5ca5270

Thanks.

Luca Boccassi

---
>From 2df90802c6f7cd84fa91ba3552d31c2fc5ca5270 Mon Sep 17 00:00:00 2001
From: Xiao Wang <xiao.w.wang@intel.com>
Date: Mon, 21 Jun 2021 16:21:04 +0800
Subject: [PATCH] vhost: check header for legacy dequeue offload

[ upstream commit 706ba48665844b859fcf0bd9526ec5da28b915da ]

When parsing the virtio net header and packet header for dequeue offload,
we need to perform sanity check on the packet header to ensure:
  - No out-of-boundary memory access.
  - The packet header and virtio_net header are valid and aligned.

Fixes: d0cf91303d73 ("vhost: add Tx offload capabilities")

Signed-off-by: Xiao Wang <xiao.w.wang@intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/virtio_net.c | 117 ++++++++++++++++++++++++++--------
 1 file changed, 89 insertions(+), 28 deletions(-)

diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 6c7c0b0f0e..e165a70afc 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -1797,14 +1797,17 @@ virtio_net_with_host_offload(struct virtio_net *dev)
 	return false;
 }
 
-static void
-parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
+static int
+parse_headers(struct rte_mbuf *m, uint8_t *l4_proto)
 {
 	struct rte_ipv4_hdr *ipv4_hdr;
 	struct rte_ipv6_hdr *ipv6_hdr;
-	void *l3_hdr = NULL;
 	struct rte_ether_hdr *eth_hdr;
 	uint16_t ethertype;
+	uint16_t data_len = rte_pktmbuf_data_len(m);
+
+	if (data_len < sizeof(struct rte_ether_hdr))
+		return -EINVAL;
 
 	eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
 
@@ -1812,6 +1815,10 @@ parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
 	ethertype = rte_be_to_cpu_16(eth_hdr->ether_type);
 
 	if (ethertype == RTE_ETHER_TYPE_VLAN) {
+		if (data_len < sizeof(struct rte_ether_hdr) +
+				sizeof(struct rte_vlan_hdr))
+			goto error;
+
 		struct rte_vlan_hdr *vlan_hdr =
 			(struct rte_vlan_hdr *)(eth_hdr + 1);
 
@@ -1819,70 +1826,118 @@ parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
 		ethertype = rte_be_to_cpu_16(vlan_hdr->eth_proto);
 	}
 
-	l3_hdr = (char *)eth_hdr + m->l2_len;
-
 	switch (ethertype) {
 	case RTE_ETHER_TYPE_IPV4:
-		ipv4_hdr = l3_hdr;
-		*l4_proto = ipv4_hdr->next_proto_id;
+		if (data_len < m->l2_len + sizeof(struct rte_ipv4_hdr))
+			goto error;
+		ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
+				m->l2_len);
 		m->l3_len = rte_ipv4_hdr_len(ipv4_hdr);
-		*l4_hdr = (char *)l3_hdr + m->l3_len;
+		if (data_len < m->l2_len + m->l3_len)
+			goto error;
 		m->ol_flags |= PKT_TX_IPV4;
+		*l4_proto = ipv4_hdr->next_proto_id;
 		break;
 	case RTE_ETHER_TYPE_IPV6:
-		ipv6_hdr = l3_hdr;
-		*l4_proto = ipv6_hdr->proto;
+		if (data_len < m->l2_len + sizeof(struct rte_ipv6_hdr))
+			goto error;
+		ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *,
+				m->l2_len);
 		m->l3_len = sizeof(struct rte_ipv6_hdr);
-		*l4_hdr = (char *)l3_hdr + m->l3_len;
 		m->ol_flags |= PKT_TX_IPV6;
+		*l4_proto = ipv6_hdr->proto;
 		break;
 	default:
-		m->l3_len = 0;
-		*l4_proto = 0;
-		*l4_hdr = NULL;
+		/* a valid L3 header is needed for further L4 parsing */
+		goto error;
+	}
+
+	/* both CSUM and GSO need a valid L4 header */
+	switch (*l4_proto) {
+	case IPPROTO_TCP:
+		if (data_len < m->l2_len + m->l3_len +
+				sizeof(struct rte_tcp_hdr))
+			goto error;
+		break;
+	case IPPROTO_UDP:
+		if (data_len < m->l2_len + m->l3_len +
+				sizeof(struct rte_udp_hdr))
+			goto error;
 		break;
+	case IPPROTO_SCTP:
+		if (data_len < m->l2_len + m->l3_len +
+				sizeof(struct rte_sctp_hdr))
+			goto error;
+		break;
+	default:
+		goto error;
 	}
+
+	return 0;
+
+error:
+	m->l2_len = 0;
+	m->l3_len = 0;
+	m->ol_flags = 0;
+	return -EINVAL;
 }
 
 static __rte_always_inline void
 vhost_dequeue_offload_legacy(struct virtio_net_hdr *hdr, struct rte_mbuf *m)
 {
-	uint16_t l4_proto = 0;
-	void *l4_hdr = NULL;
+	uint8_t l4_proto = 0;
 	struct rte_tcp_hdr *tcp_hdr = NULL;
+	uint16_t tcp_len;
+	uint16_t data_len = rte_pktmbuf_data_len(m);
+
+	if (parse_headers(m, &l4_proto) < 0)
+		return;
 
-	parse_ethernet(m, &l4_proto, &l4_hdr);
 	if (hdr->flags == VIRTIO_NET_HDR_F_NEEDS_CSUM) {
 		if (hdr->csum_start == (m->l2_len + m->l3_len)) {
 			switch (hdr->csum_offset) {
 			case (offsetof(struct rte_tcp_hdr, cksum)):
-				if (l4_proto == IPPROTO_TCP)
-					m->ol_flags |= PKT_TX_TCP_CKSUM;
+				if (l4_proto != IPPROTO_TCP)
+					goto error;
+				m->ol_flags |= PKT_TX_TCP_CKSUM;
 				break;
 			case (offsetof(struct rte_udp_hdr, dgram_cksum)):
-				if (l4_proto == IPPROTO_UDP)
-					m->ol_flags |= PKT_TX_UDP_CKSUM;
+				if (l4_proto != IPPROTO_UDP)
+					goto error;
+				m->ol_flags |= PKT_TX_UDP_CKSUM;
 				break;
 			case (offsetof(struct rte_sctp_hdr, cksum)):
-				if (l4_proto == IPPROTO_SCTP)
-					m->ol_flags |= PKT_TX_SCTP_CKSUM;
+				if (l4_proto != IPPROTO_SCTP)
+					goto error;
+				m->ol_flags |= PKT_TX_SCTP_CKSUM;
 				break;
 			default:
-				break;
+				goto error;
 			}
+		} else {
+			goto error;
 		}
 	}
 
-	if (l4_hdr && hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
+	if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
 		switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
 		case VIRTIO_NET_HDR_GSO_TCPV4:
 		case VIRTIO_NET_HDR_GSO_TCPV6:
-			tcp_hdr = l4_hdr;
+			if (l4_proto != IPPROTO_TCP)
+				goto error;
+			tcp_hdr = rte_pktmbuf_mtod_offset(m,
+					struct rte_tcp_hdr *,
+					m->l2_len + m->l3_len);
+			tcp_len = (tcp_hdr->data_off & 0xf0) >> 2;
+			if (data_len < m->l2_len + m->l3_len + tcp_len)
+				goto error;
 			m->ol_flags |= PKT_TX_TCP_SEG;
 			m->tso_segsz = hdr->gso_size;
-			m->l4_len = (tcp_hdr->data_off & 0xf0) >> 2;
+			m->l4_len = tcp_len;
 			break;
 		case VIRTIO_NET_HDR_GSO_UDP:
+			if (l4_proto != IPPROTO_UDP)
+				goto error;
 			m->ol_flags |= PKT_TX_UDP_SEG;
 			m->tso_segsz = hdr->gso_size;
 			m->l4_len = sizeof(struct rte_udp_hdr);
@@ -1890,9 +1945,15 @@ vhost_dequeue_offload_legacy(struct virtio_net_hdr *hdr, struct rte_mbuf *m)
 		default:
 			VHOST_LOG_DATA(WARNING,
 				"unsupported gso type %u.\n", hdr->gso_type);
-			break;
+			goto error;
 		}
 	}
+	return;
+
+error:
+	m->l2_len = 0;
+	m->l3_len = 0;
+	m->ol_flags = 0;
 }
 
 static __rte_always_inline void
-- 
2.30.2

---
  Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- -	2021-07-26 13:53:17.007293391 +0100
+++ 0022-vhost-check-header-for-legacy-dequeue-offload.patch	2021-07-26 13:53:15.841292454 +0100
@@ -1 +1 @@
-From 706ba48665844b859fcf0bd9526ec5da28b915da Mon Sep 17 00:00:00 2001
+From 2df90802c6f7cd84fa91ba3552d31c2fc5ca5270 Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit 706ba48665844b859fcf0bd9526ec5da28b915da ]
+
@@ -12 +13,0 @@
-Cc: stable@dpdk.org
@@ -17 +18 @@
- lib/vhost/virtio_net.c | 117 +++++++++++++++++++++++++++++++----------
+ lib/librte_vhost/virtio_net.c | 117 ++++++++++++++++++++++++++--------
@@ -20,5 +21,5 @@
-diff --git a/lib/vhost/virtio_net.c b/lib/vhost/virtio_net.c
-index b93482587c..aa30d147b6 100644
---- a/lib/vhost/virtio_net.c
-+++ b/lib/vhost/virtio_net.c
-@@ -2259,14 +2259,17 @@ virtio_net_with_host_offload(struct virtio_net *dev)
+diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
+index 6c7c0b0f0e..e165a70afc 100644
+--- a/lib/librte_vhost/virtio_net.c
++++ b/lib/librte_vhost/virtio_net.c
+@@ -1797,14 +1797,17 @@ virtio_net_with_host_offload(struct virtio_net *dev)
@@ -45 +46 @@
-@@ -2274,6 +2277,10 @@ parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
+@@ -1812,6 +1815,10 @@ parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
@@ -56 +57 @@
-@@ -2281,70 +2288,118 @@ parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
+@@ -1819,70 +1826,118 @@ parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
@@ -199 +200 @@
-@@ -2352,9 +2407,15 @@ vhost_dequeue_offload_legacy(struct virtio_net_hdr *hdr, struct rte_mbuf *m)
+@@ -1890,9 +1945,15 @@ vhost_dequeue_offload_legacy(struct virtio_net_hdr *hdr, struct rte_mbuf *m)