svn commit: r343238 - head/sys/dev/usb/wlan

Andriy Voskoboinyk avos at FreeBSD.org
Mon Jan 21 00:53:40 UTC 2019


Author: avos
Date: Mon Jan 21 00:53:38 2019
New Revision: 343238
URL: https://svnweb.freebsd.org/changeset/base/343238

Log:
  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.
  
  MFC after:	1 week

Modified:
  head/sys/dev/usb/wlan/if_urtw.c
  head/sys/dev/usb/wlan/if_urtwvar.h

Modified: head/sys/dev/usb/wlan/if_urtw.c
==============================================================================
--- head/sys/dev/usb/wlan/if_urtw.c	Mon Jan 21 00:32:04 2019	(r343237)
+++ head/sys/dev/usb/wlan/if_urtw.c	Mon Jan 21 00:53:38 2019	(r343238)
@@ -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: head/sys/dev/usb/wlan/if_urtwvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwvar.h	Mon Jan 21 00:32:04 2019	(r343237)
+++ head/sys/dev/usb/wlan/if_urtwvar.h	Mon Jan 21 00:53:38 2019	(r343238)
@@ -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


More information about the svn-src-all mailing list