Author: hselasky
Date: Thu Aug  3 07:50:46 2017
New Revision: 321980
URL: https://svnweb.freebsd.org/changeset/base/321980

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

Modified:
  stable/11/sys/dev/usb/wlan/if_rsu.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/usb/wlan/if_rsu.c
==============================================================================
--- stable/11/sys/dev/usb/wlan/if_rsu.c Thu Aug  3 07:42:08 2017        
(r321979)
+++ stable/11/sys/dev/usb/wlan/if_rsu.c Thu Aug  3 07:50:46 2017        
(r321980)
@@ -1481,6 +1481,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)
 {
@@ -1489,28 +1491,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;
@@ -1523,7 +1528,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;
@@ -2621,6 +2626,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)
 {
@@ -2628,7 +2635,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;
@@ -2679,7 +2686,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;
_______________________________________________
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"

Reply via email to