Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 30 Jul 2017 16:45:28 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r321722 - head/sys/dev/usb/wlan
Message-ID:  <201707301645.v6UGjSi6040894@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Sun Jul 30 16:45:28 2017
New Revision: 321722
URL: https://svnweb.freebsd.org/changeset/base/321722

Log:
  Properly range check length of parsed information elements in RSU driver.
  
  Found by:		Ilja van Sprundel <ivansprundel@ioactive.com>
  MFC after:		3 days
  Sponsored by:		Mellanox Technologies

Modified:
  head/sys/dev/usb/wlan/if_rsu.c

Modified: head/sys/dev/usb/wlan/if_rsu.c
==============================================================================
--- head/sys/dev/usb/wlan/if_rsu.c	Sun Jul 30 16:17:06 2017	(r321721)
+++ head/sys/dev/usb/wlan/if_rsu.c	Sun Jul 30 16:45:28 2017	(r321722)
@@ -2031,6 +2031,8 @@ rsu_hwrssi_to_rssi(struct rsu_softc *sc, int hw_rssi)
 	return (v);
 }
 
+CTASSERT(MCLBYTES > sizeof(struct ieee80211_frame));
+
 static void
 rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
 {
@@ -2039,28 +2041,31 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, i
 	struct ndis_wlan_bssid_ex *bss;
 	struct ieee80211_rx_stats rxs;
 	struct mbuf *m;
-	int pktlen;
+	uint32_t ieslen;
+	uint32_t pktlen;
 
 	if (__predict_false(len < sizeof(*bss)))
 		return;
 	bss = (struct ndis_wlan_bssid_ex *)buf;
-	if (__predict_false(len < sizeof(*bss) + le32toh(bss->ieslen)))
+	ieslen = le32toh(bss->ieslen);
+	/* range check length of information element */
+	if (__predict_false(ieslen > (uint32_t)(len - sizeof(*bss))))
 		return;
 
 	RSU_DPRINTF(sc, RSU_DEBUG_SCAN,
 	    "%s: found BSS %s: len=%d chan=%d inframode=%d "
 	    "networktype=%d privacy=%d, RSSI=%d\n",
 	    __func__,
-	    ether_sprintf(bss->macaddr), le32toh(bss->len),
+	    ether_sprintf(bss->macaddr), ieslen,
 	    le32toh(bss->config.dsconfig), le32toh(bss->inframode),
 	    le32toh(bss->networktype), le32toh(bss->privacy),
 	    le32toh(bss->rssi));
 
 	/* Build a fake beacon frame to let net80211 do all the parsing. */
 	/* XXX TODO: just call the new scan API methods! */
-	pktlen = sizeof(*wh) + le32toh(bss->ieslen);
-	if (__predict_false(pktlen > MCLBYTES))
+	if (__predict_false(ieslen > (size_t)(MCLBYTES - sizeof(*wh))))
 		return;
+	pktlen = sizeof(*wh) + ieslen;
 	m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
 	if (__predict_false(m == NULL))
 		return;
@@ -2073,7 +2078,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, i
 	IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr);
 	IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
 	*(uint16_t *)wh->i_seq = 0;
-	memcpy(&wh[1], (uint8_t *)&bss[1], le32toh(bss->ieslen));
+	memcpy(&wh[1], (uint8_t *)&bss[1], ieslen);
 
 	/* Finalize mbuf. */
 	m->m_pkthdr.len = m->m_len = pktlen;
@@ -3373,6 +3378,8 @@ rsu_fw_loadsection(struct rsu_softc *sc, const uint8_t
 	return (0);
 }
 
+CTASSERT(sizeof(size_t) >= sizeof(uint32_t));
+
 static int
 rsu_load_firmware(struct rsu_softc *sc)
 {
@@ -3380,7 +3387,7 @@ rsu_load_firmware(struct rsu_softc *sc)
 	struct r92s_fw_priv *dmem;
 	struct ieee80211com *ic = &sc->sc_ic;
 	const uint8_t *imem, *emem;
-	int imemsz, ememsz;
+	uint32_t imemsz, ememsz;
 	const struct firmware *fw;
 	size_t size;
 	uint32_t reg;
@@ -3432,7 +3439,8 @@ rsu_load_firmware(struct rsu_softc *sc)
 	imemsz = le32toh(hdr->imemsz);
 	ememsz = le32toh(hdr->sramsz);
 	/* Check that all FW sections fit in image. */
-	if (size < sizeof(*hdr) + imemsz + ememsz) {
+	if (imemsz > (size_t)(size - sizeof(*hdr)) ||
+	    ememsz > (size_t)(size - sizeof(*hdr) - imemsz)) {
 		device_printf(sc->sc_dev, "firmware too short\n");
 		error = EINVAL;
 		goto fail;



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