svn commit: r305176 - head/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Thu Sep 1 06:05:09 UTC 2016
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);
}
/*
More information about the svn-src-all
mailing list