summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2017-08-03 07:50:46 +0000
committerhselasky <hselasky@FreeBSD.org>2017-08-03 07:50:46 +0000
commitcfc3e00a8e6f494c977d5453cbd629e7710ad40b (patch)
treef8fc959d16782fbf88d01d34edca3d0038bd21f4
parent730a77d80324dec15c69555dd5959c4810268308 (diff)
downloadFreeBSD-src-cfc3e00a8e6f494c977d5453cbd629e7710ad40b.zip
FreeBSD-src-cfc3e00a8e6f494c977d5453cbd629e7710ad40b.tar.gz
MFC r321722:
Properly range check length of parsed information elements in RSU driver. Found by: Ilja van Sprundel <ivansprundel@ioactive.com> Sponsored by: Mellanox Technologies
-rw-r--r--sys/dev/usb/wlan/if_rsu.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c
index 0b5987a..4ec6847 100644
--- a/sys/dev/usb/wlan/if_rsu.c
+++ b/sys/dev/usb/wlan/if_rsu.c
@@ -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, int len)
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, int len)
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 *buf, int len)
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;
OpenPOWER on IntegriCloud