Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Jan 2019 01:47:17 +0000 (UTC)
From:      Andriy Voskoboinyk <avos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r343514 - stable/12/sys/dev/usb/wlan
Message-ID:  <201901280147.x0S1lHXw001415@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avos
Date: Mon Jan 28 01:47:16 2019
New Revision: 343514
URL: https://svnweb.freebsd.org/changeset/base/343514

Log:
  MFC r343238:
  urtw(4): add length checks in Rx path.
  
  - Check if buffer can contain Rx descriptor before accessing it.
  - Verify upper / lower bounds for frame length.
  - Do not pass too short frames into ieee80211_find_rxnode().
  
  While here:
  - Move cleanup to the function end.
  - Reuse IEEE80211_IS_DATA() macro.

Modified:
  stable/12/sys/dev/usb/wlan/if_urtw.c
  stable/12/sys/dev/usb/wlan/if_urtwvar.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/usb/wlan/if_urtw.c
==============================================================================
--- stable/12/sys/dev/usb/wlan/if_urtw.c	Mon Jan 28 01:37:36 2019	(r343513)
+++ stable/12/sys/dev/usb/wlan/if_urtw.c	Mon Jan 28 01:47:16 2019	(r343514)
@@ -3933,21 +3933,18 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *da
 
 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
 
-	if (actlen < (int)URTW_MIN_RXBUFSZ) {
-		counter_u64_add(ic->ic_ierrors, 1);
-		return (NULL);
-	}
-
 	if (sc->sc_flags & URTW_RTL8187B) {
 		struct urtw_8187b_rxhdr *rx;
 
+		if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN)
+			goto fail;
+
 		rx = (struct urtw_8187b_rxhdr *)(data->buf +
 		    (actlen - (sizeof(struct urtw_8187b_rxhdr))));
 		flen = le32toh(rx->flag) & 0xfff;
-		if (flen > actlen) {
-			counter_u64_add(ic->ic_ierrors, 1);
-			return (NULL);
-		}
+		if (flen > actlen - sizeof(*rx))
+			goto fail;
+
 		rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
 		/* XXX correct? */
 		rssi = rx->rssi & URTW_RX_RSSI_MASK;
@@ -3955,13 +3952,14 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *da
 	} else {
 		struct urtw_8187l_rxhdr *rx;
 
+		if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN)
+			goto fail;
+
 		rx = (struct urtw_8187l_rxhdr *)(data->buf +
 		    (actlen - (sizeof(struct urtw_8187l_rxhdr))));
 		flen = le32toh(rx->flag) & 0xfff;
-		if (flen > actlen) {
-			counter_u64_add(ic->ic_ierrors, 1);
-			return (NULL);
-		}
+		if (flen > actlen - sizeof(*rx))
+			goto fail;
 
 		rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
 		/* XXX correct? */
@@ -3969,11 +3967,12 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *da
 		noise = rx->noise;
 	}
 
+	if (flen < IEEE80211_ACK_LEN)
+		goto fail;
+
 	mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
-	if (mnew == NULL) {
-		counter_u64_add(ic->ic_ierrors, 1);
-		return (NULL);
-	}
+	if (mnew == NULL)
+		goto fail;
 
 	m = data->m;
 	data->m = mnew;
@@ -3992,13 +3991,17 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *da
 	}
 
 	wh = mtod(m, struct ieee80211_frame *);
-	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA)
+	if (IEEE80211_IS_DATA(wh))
 		sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
 
 	*rssi_p = rssi;
 	*nf_p = noise;		/* XXX correct? */
 
 	return (m);
+
+fail:
+	counter_u64_add(ic->ic_ierrors, 1);
+	return (NULL);
 }
 
 static void
@@ -4006,7 +4009,6 @@ urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error
 {
 	struct urtw_softc *sc = usbd_xfer_softc(xfer);
 	struct ieee80211com *ic = &sc->sc_ic;
-	struct ieee80211_frame *wh;
 	struct ieee80211_node *ni;
 	struct mbuf *m = NULL;
 	struct urtw_data *data;
@@ -4044,9 +4046,13 @@ setup:
 		 */
 		URTW_UNLOCK(sc);
 		if (m != NULL) {
-			wh = mtod(m, struct ieee80211_frame *);
-			ni = ieee80211_find_rxnode(ic,
-			    (struct ieee80211_frame_min *)wh);
+			if (m->m_pkthdr.len >=
+			    sizeof(struct ieee80211_frame_min)) {
+				ni = ieee80211_find_rxnode(ic,
+				    mtod(m, struct ieee80211_frame_min *));
+			} else
+				ni = NULL;
+
 			if (ni != NULL) {
 				(void) ieee80211_input(ni, m, rssi, nf);
 				/* node is no longer needed */

Modified: stable/12/sys/dev/usb/wlan/if_urtwvar.h
==============================================================================
--- stable/12/sys/dev/usb/wlan/if_urtwvar.h	Mon Jan 28 01:37:36 2019	(r343513)
+++ stable/12/sys/dev/usb/wlan/if_urtwvar.h	Mon Jan 28 01:47:16 2019	(r343514)
@@ -47,10 +47,6 @@ struct urtw_data {
 };
 typedef STAILQ_HEAD(, urtw_data) urtw_datahead;
 
-/* XXX not correct..  */
-#define	URTW_MIN_RXBUFSZ						\
-	(sizeof(struct ieee80211_frame_min))
-
 #define URTW_RX_DATA_LIST_COUNT		4
 #define URTW_TX_DATA_LIST_COUNT		16
 #define URTW_RX_MAXSIZE			0x9c4



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201901280147.x0S1lHXw001415>