Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Sep 2016 04:47:31 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r305408 - head/sys/dev/hyperv/netvsc
Message-ID:  <201609050447.u854lVZ6003513@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Mon Sep  5 04:47:31 2016
New Revision: 305408
URL: https://svnweb.freebsd.org/changeset/base/305408

Log:
  hyperv/hn: Stringent NVS RNDIS packets length checks.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D7755

Modified:
  head/sys/dev/hyperv/netvsc/hv_net_vsc.c

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.c	Mon Sep  5 03:39:04 2016	(r305407)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.c	Mon Sep  5 04:47:31 2016	(r305408)
@@ -742,32 +742,53 @@ hv_nv_on_receive(struct hn_softc *sc, st
 {
 	const struct vmbus_chanpkt_rxbuf *pkt;
 	const struct hn_nvs_hdr *nvs_hdr;
-	int count = 0;
-	int i = 0;
+	int count, i, hlen;
 
-	/* Make sure that this is a RNDIS message. */
+	if (__predict_false(VMBUS_CHANPKT_DATALEN(pkthdr) < sizeof(*nvs_hdr))) {
+		if_printf(rxr->hn_ifp, "invalid nvs RNDIS\n");
+		return;
+	}
 	nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr);
+
+	/* Make sure that this is a RNDIS message. */
 	if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) {
 		if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n",
 		    nvs_hdr->nvs_type);
 		return;
 	}
-	
+
+	hlen = VMBUS_CHANPKT_GETLEN(pkthdr->cph_hlen);
+	if (__predict_false(hlen < sizeof(*pkt))) {
+		if_printf(rxr->hn_ifp, "invalid rxbuf chanpkt\n");
+		return;
+	}
 	pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr;
 
-	if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) {
-		if_printf(rxr->hn_ifp, "rxbuf_id %d is invalid!\n",
+	if (__predict_false(pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID)) {
+		if_printf(rxr->hn_ifp, "invalid rxbuf_id 0x%08x\n",
 		    pkt->cp_rxbuf_id);
 		return;
 	}
 
 	count = pkt->cp_rxbuf_cnt;
+	if (__predict_false(hlen <
+	    __offsetof(struct vmbus_chanpkt_rxbuf, cp_rxbuf[count]))) {
+		if_printf(rxr->hn_ifp, "invalid rxbuf_cnt %d\n", count);
+		return;
+	}
 
 	/* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
-	for (i = 0; i < count; i++) {
-		hv_rf_on_receive(sc, rxr,
-		    rxr->hn_rxbuf + pkt->cp_rxbuf[i].rb_ofs,
-		    pkt->cp_rxbuf[i].rb_len);
+	for (i = 0; i < count; ++i) {
+		int ofs, len;
+
+		ofs = pkt->cp_rxbuf[i].rb_ofs;
+		len = pkt->cp_rxbuf[i].rb_len;
+		if (__predict_false(ofs + len > NETVSC_RECEIVE_BUFFER_SIZE)) {
+			if_printf(rxr->hn_ifp, "%dth RNDIS msg overflow rxbuf, "
+			    "ofs %d, len %d\n", i, ofs, len);
+			continue;
+		}
+		hv_rf_on_receive(sc, rxr, rxr->hn_rxbuf + ofs, len);
 	}
 	
 	/*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609050447.u854lVZ6003513>