hyperv/hn: Stringent NVS RNDIS packets length checks.

MFC after:	1 week
Sponsored by:	Microsoft
Differential Revision:	https://reviews.freebsd.org/D7755
This commit is contained in:
Sepherosa Ziehau 2016-09-05 04:47:31 +00:00
parent dc65be7a3d
commit 7a466137f0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=305408

View File

@ -742,32 +742,53 @@ hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
{ {
const struct vmbus_chanpkt_rxbuf *pkt; const struct vmbus_chanpkt_rxbuf *pkt;
const struct hn_nvs_hdr *nvs_hdr; const struct hn_nvs_hdr *nvs_hdr;
int count = 0; int count, i, hlen;
int i = 0;
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. */ /* Make sure that this is a RNDIS message. */
nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr);
if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) { if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) {
if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n", if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n",
nvs_hdr->nvs_type); nvs_hdr->nvs_type);
return; 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; pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr;
if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) { if (__predict_false(pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID)) {
if_printf(rxr->hn_ifp, "rxbuf_id %d is invalid!\n", if_printf(rxr->hn_ifp, "invalid rxbuf_id 0x%08x\n",
pkt->cp_rxbuf_id); pkt->cp_rxbuf_id);
return; return;
} }
count = pkt->cp_rxbuf_cnt; 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 */ /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
for (i = 0; i < count; i++) { for (i = 0; i < count; ++i) {
hv_rf_on_receive(sc, rxr, int ofs, len;
rxr->hn_rxbuf + pkt->cp_rxbuf[i].rb_ofs,
pkt->cp_rxbuf[i].rb_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);
} }
/* /*