Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Sep 2016 06:05:08 +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: r305176 - head/sys/dev/hyperv/netvsc
Message-ID:  <201609010605.u81658o7014139@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Thu Sep  1 06:05:08 2016
New Revision: 305176
URL: https://svnweb.freebsd.org/changeset/base/305176

Log:
  hyperv/hn: Stringent per-packet-info verification.
  
  While I'm here, minor style changes.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D7709

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

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Thu Sep  1 05:40:13 2016	(r305175)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Thu Sep  1 06:05:08 2016	(r305176)
@@ -153,8 +153,8 @@ hv_rf_receive_indicate_status(struct hn_
 static int
 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
 {
-	const rndis_per_packet_info *ppi;
-	uint32_t mask, len;
+	const struct rndis_pktinfo *pi;
+	uint32_t mask = 0, len;
 
 	info->vlan_info = NULL;
 	info->csum_info = NULL;
@@ -162,70 +162,80 @@ hv_rf_find_recvinfo(const rndis_packet *
 	info->hash_value = NULL;
 
 	if (rpkt->per_pkt_info_offset == 0)
-		return 0;
+		return (0);
+	if (__predict_false(rpkt->per_pkt_info_offset &
+	    (RNDIS_PKTINFO_ALIGN - 1)))
+		return (EINVAL);
+	if (__predict_false(rpkt->per_pkt_info_offset <
+	    RNDIS_PACKET_MSG_OFFSET_MIN))
+		return (EINVAL);
 
-	ppi = (const rndis_per_packet_info *)
+	pi = (const struct rndis_pktinfo *)
 	    ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
 	len = rpkt->per_pkt_info_length;
-	mask = 0;
 
 	while (len != 0) {
-		const void *ppi_dptr;
-		uint32_t ppi_dlen;
+		const void *data;
+		uint32_t dlen;
 
-		if (__predict_false(ppi->size < ppi->per_packet_info_offset))
-			return EINVAL;
-		ppi_dlen = ppi->size - ppi->per_packet_info_offset;
-		ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
+		if (__predict_false(len < sizeof(*pi)))
+			return (EINVAL);
+		if (__predict_false(len < pi->rm_size))
+			return (EINVAL);
+		len -= pi->rm_size;
+
+		if (__predict_false(pi->rm_size & (RNDIS_PKTINFO_ALIGN - 1)))
+			return (EINVAL);
+		if (__predict_false(pi->rm_size < pi->rm_pktinfooffset))
+			return (EINVAL);
+		dlen = pi->rm_size - pi->rm_pktinfooffset;
+		data = pi->rm_data;
 
-		switch (ppi->type) {
+		switch (pi->rm_type) {
 		case ieee_8021q_info:
-			if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
-				return EINVAL;
-			info->vlan_info = ppi_dptr;
+			if (__predict_false(dlen < sizeof(ndis_8021q_info)))
+				return (EINVAL);
+			info->vlan_info = data;
 			mask |= HV_RF_RECVINFO_VLAN;
 			break;
 
 		case tcpip_chksum_info:
-			if (__predict_false(ppi_dlen <
+			if (__predict_false(dlen <
 			    sizeof(rndis_tcp_ip_csum_info)))
-				return EINVAL;
-			info->csum_info = ppi_dptr;
+				return (EINVAL);
+			info->csum_info = data;
 			mask |= HV_RF_RECVINFO_CSUM;
 			break;
 
 		case nbl_hash_value:
-			if (__predict_false(ppi_dlen <
+			if (__predict_false(dlen <
 			    sizeof(struct rndis_hash_value)))
-				return EINVAL;
-			info->hash_value = ppi_dptr;
+				return (EINVAL);
+			info->hash_value = data;
 			mask |= HV_RF_RECVINFO_HASHVAL;
 			break;
 
 		case nbl_hash_info:
-			if (__predict_false(ppi_dlen <
+			if (__predict_false(dlen <
 			    sizeof(struct rndis_hash_info)))
-				return EINVAL;
-			info->hash_info = ppi_dptr;
+				return (EINVAL);
+			info->hash_info = data;
 			mask |= HV_RF_RECVINFO_HASHINF;
 			break;
 
 		default:
-			goto skip;
+			goto next;
 		}
 
 		if (mask == HV_RF_RECVINFO_ALL) {
 			/* All found; done */
 			break;
 		}
-skip:
-		if (__predict_false(len < ppi->size))
-			return EINVAL;
-		len -= ppi->size;
-		ppi = (const rndis_per_packet_info *)
-		    ((const uint8_t *)ppi + ppi->size);
+next:
+		pi = (const struct rndis_pktinfo *)
+		    ((const uint8_t *)pi + pi->rm_size);
 	}
-	return 0;
+	return (0);
 }
 
 /*



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