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
This commit is contained in:
parent
b7121ba36f
commit
51c7a87f69
@ -2031,6 +2031,8 @@ rsu_hwrssi_to_rssi(struct rsu_softc *sc, int hw_rssi)
|
|||||||
return (v);
|
return (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CTASSERT(MCLBYTES > sizeof(struct ieee80211_frame));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
|
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, int len)
|
|||||||
struct ndis_wlan_bssid_ex *bss;
|
struct ndis_wlan_bssid_ex *bss;
|
||||||
struct ieee80211_rx_stats rxs;
|
struct ieee80211_rx_stats rxs;
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
int pktlen;
|
uint32_t ieslen;
|
||||||
|
uint32_t pktlen;
|
||||||
|
|
||||||
if (__predict_false(len < sizeof(*bss)))
|
if (__predict_false(len < sizeof(*bss)))
|
||||||
return;
|
return;
|
||||||
bss = (struct ndis_wlan_bssid_ex *)buf;
|
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;
|
return;
|
||||||
|
|
||||||
RSU_DPRINTF(sc, RSU_DEBUG_SCAN,
|
RSU_DPRINTF(sc, RSU_DEBUG_SCAN,
|
||||||
"%s: found BSS %s: len=%d chan=%d inframode=%d "
|
"%s: found BSS %s: len=%d chan=%d inframode=%d "
|
||||||
"networktype=%d privacy=%d, RSSI=%d\n",
|
"networktype=%d privacy=%d, RSSI=%d\n",
|
||||||
__func__,
|
__func__,
|
||||||
ether_sprintf(bss->macaddr), le32toh(bss->len),
|
ether_sprintf(bss->macaddr), ieslen,
|
||||||
le32toh(bss->config.dsconfig), le32toh(bss->inframode),
|
le32toh(bss->config.dsconfig), le32toh(bss->inframode),
|
||||||
le32toh(bss->networktype), le32toh(bss->privacy),
|
le32toh(bss->networktype), le32toh(bss->privacy),
|
||||||
le32toh(bss->rssi));
|
le32toh(bss->rssi));
|
||||||
|
|
||||||
/* Build a fake beacon frame to let net80211 do all the parsing. */
|
/* Build a fake beacon frame to let net80211 do all the parsing. */
|
||||||
/* XXX TODO: just call the new scan API methods! */
|
/* XXX TODO: just call the new scan API methods! */
|
||||||
pktlen = sizeof(*wh) + le32toh(bss->ieslen);
|
if (__predict_false(ieslen > (size_t)(MCLBYTES - sizeof(*wh))))
|
||||||
if (__predict_false(pktlen > MCLBYTES))
|
|
||||||
return;
|
return;
|
||||||
|
pktlen = sizeof(*wh) + ieslen;
|
||||||
m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
|
m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||||
if (__predict_false(m == NULL))
|
if (__predict_false(m == NULL))
|
||||||
return;
|
return;
|
||||||
@ -2073,7 +2078,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_addr2, bss->macaddr);
|
||||||
IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
|
IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
|
||||||
*(uint16_t *)wh->i_seq = 0;
|
*(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. */
|
/* Finalize mbuf. */
|
||||||
m->m_pkthdr.len = m->m_len = pktlen;
|
m->m_pkthdr.len = m->m_len = pktlen;
|
||||||
@ -3373,6 +3378,8 @@ rsu_fw_loadsection(struct rsu_softc *sc, const uint8_t *buf, int len)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CTASSERT(sizeof(size_t) >= sizeof(uint32_t));
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rsu_load_firmware(struct rsu_softc *sc)
|
rsu_load_firmware(struct rsu_softc *sc)
|
||||||
{
|
{
|
||||||
@ -3380,7 +3387,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
|||||||
struct r92s_fw_priv *dmem;
|
struct r92s_fw_priv *dmem;
|
||||||
struct ieee80211com *ic = &sc->sc_ic;
|
struct ieee80211com *ic = &sc->sc_ic;
|
||||||
const uint8_t *imem, *emem;
|
const uint8_t *imem, *emem;
|
||||||
int imemsz, ememsz;
|
uint32_t imemsz, ememsz;
|
||||||
const struct firmware *fw;
|
const struct firmware *fw;
|
||||||
size_t size;
|
size_t size;
|
||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
@ -3432,7 +3439,8 @@ rsu_load_firmware(struct rsu_softc *sc)
|
|||||||
imemsz = le32toh(hdr->imemsz);
|
imemsz = le32toh(hdr->imemsz);
|
||||||
ememsz = le32toh(hdr->sramsz);
|
ememsz = le32toh(hdr->sramsz);
|
||||||
/* Check that all FW sections fit in image. */
|
/* 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");
|
device_printf(sc->sc_dev, "firmware too short\n");
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user