svn commit: r305408 - head/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Mon Sep 5 04:47:33 UTC 2016
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);
}
/*
More information about the svn-src-head
mailing list