svn commit: r305411 - head/sys/dev/hyperv/netvsc

Sepherosa Ziehau sephe at FreeBSD.org
Mon Sep 5 05:07:42 UTC 2016


Author: sephe
Date: Mon Sep  5 05:07:40 2016
New Revision: 305411
URL: https://svnweb.freebsd.org/changeset/base/305411

Log:
  hyperv/hn: Stringent RNDIS control message length check.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D7758

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

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Mon Sep  5 04:56:56 2016	(r305410)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Mon Sep  5 05:07:40 2016	(r305411)
@@ -72,7 +72,7 @@ __FBSDID("$FreeBSD$");
  * Forward declarations
  */
 static void hv_rf_receive_indicate_status(struct hn_softc *sc,
-    const rndis_msg *response);
+    const void *data, int dlen);
 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
     const void *data, int dlen);
 static int hv_rf_query_device_mac(struct hn_softc *sc, uint8_t *eaddr);
@@ -131,21 +131,29 @@ hv_set_rppi_data(rndis_msg *rndis_mesg, 
  * RNDIS filter receive indicate status
  */
 static void 
-hv_rf_receive_indicate_status(struct hn_softc *sc, const rndis_msg *response)
+hv_rf_receive_indicate_status(struct hn_softc *sc, const void *data, int dlen)
 {
-	const rndis_indicate_status *indicate = &response->msg.indicate_status;
-		
-	switch(indicate->status) {
+	const struct rndis_status_msg *msg;
+
+	if (dlen < sizeof(*msg)) {
+		if_printf(sc->hn_ifp, "invalid RNDIS status\n");
+		return;
+	}
+	msg = data;
+
+	switch (msg->rm_status) {
 	case RNDIS_STATUS_MEDIA_CONNECT:
 		netvsc_linkstatus_callback(sc, 1);
 		break;
+
 	case RNDIS_STATUS_MEDIA_DISCONNECT:
 		netvsc_linkstatus_callback(sc, 0);
 		break;
+
 	default:
 		/* TODO: */
-		if_printf(sc->hn_ifp,
-		    "unknown status %d received\n", indicate->status);
+		if_printf(sc->hn_ifp, "unknown RNDIS status 0x%08x\n",
+		    msg->rm_status);
 		break;
 	}
 }
@@ -283,34 +291,41 @@ hv_rf_receive_data(struct hn_rx_ring *rx
 /*
  * RNDIS filter on receive
  */
-int
+void
 hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
     const void *data, int dlen)
 {
-	const rndis_msg *rndis_hdr;
 	const struct rndis_comp_hdr *comp;
+	const struct rndis_msghdr *hdr;
+
+	if (__predict_false(dlen < sizeof(*hdr))) {
+		if_printf(rxr->hn_ifp, "invalid RNDIS msg\n");
+		return;
+	}
+	hdr = data;
 
-	rndis_hdr = data;
-	switch (rndis_hdr->ndis_msg_type) {
-	/* data message */
+	switch (hdr->rm_type) {
 	case REMOTE_NDIS_PACKET_MSG:
 		hv_rf_receive_data(rxr, data, dlen);
 		break;
 
-	/* completion messages */
 	case REMOTE_NDIS_INITIALIZE_CMPLT:
 	case REMOTE_NDIS_QUERY_CMPLT:
 	case REMOTE_NDIS_SET_CMPLT:
-	case REMOTE_NDIS_KEEPALIVE_CMPLT:
+	case REMOTE_NDIS_KEEPALIVE_CMPLT:	/* unused */
+		if (dlen < sizeof(*comp)) {
+			if_printf(rxr->hn_ifp, "invalid RNDIS cmplt\n");
+			return;
+		}
 		comp = data;
+
 		KASSERT(comp->rm_rid > HN_RNDIS_RID_COMPAT_MAX,
-		    ("invalid rid 0x%08x\n", comp->rm_rid));
+		    ("invalid RNDIS rid 0x%08x\n", comp->rm_rid));
 		vmbus_xact_ctx_wakeup(sc->hn_xact, comp, dlen);
 		break;
 
-	/* notification message */
 	case REMOTE_NDIS_INDICATE_STATUS_MSG:
-		hv_rf_receive_indicate_status(sc, rndis_hdr);
+		hv_rf_receive_indicate_status(sc, data, dlen);
 		break;
 
 	case REMOTE_NDIS_RESET_CMPLT:
@@ -321,15 +336,14 @@ hv_rf_on_receive(struct hn_softc *sc, st
 		 * RESET is not issued by hn(4), so this message should
 		 * _not_ be observed.
 		 */
-		if_printf(sc->hn_ifp, "RESET CMPLT received\n");
+		if_printf(rxr->hn_ifp, "RESET cmplt received\n");
 		break;
 
 	default:
-		if_printf(sc->hn_ifp, "unknown RNDIS message 0x%x\n",
-			rndis_hdr->ndis_msg_type);
+		if_printf(rxr->hn_ifp, "unknown RNDIS msg 0x%x\n",
+		    hdr->rm_type);
 		break;
 	}
-	return (0);
 }
 
 /*

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.h	Mon Sep  5 04:56:56 2016	(r305410)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.h	Mon Sep  5 05:07:40 2016	(r305411)
@@ -40,7 +40,7 @@
  */
 struct hn_rx_ring;
 
-int hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
+void hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
     const void *data, int dlen);
 void hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr);
 int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int *nchan,


More information about the svn-src-head mailing list