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, _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"