Index: sys/dev/usb/wlan/if_upgt.c =================================================================== --- sys/dev/usb/wlan/if_upgt.c +++ sys/dev/usb/wlan/if_upgt.c @@ -1043,7 +1043,7 @@ struct ieee80211com *ic = &sc->sc_ic; struct upgt_eeprom_header *eeprom_header; struct upgt_eeprom_option *eeprom_option; - uint16_t option_len; + uint32_t option_len; uint16_t option_type; uint16_t preamble_len; int option_end = 0; @@ -1058,7 +1058,9 @@ /* sanity check */ if (eeprom_option >= (struct upgt_eeprom_option *) - (sc->sc_eeprom + UPGT_EEPROM_SIZE)) { + (sc->sc_eeprom + UPGT_EEPROM_SIZE) || + eeprom_option < (struct upgt_eeprom_option *) + sc->sc_eeprom) { return (EINVAL); } @@ -1763,7 +1765,7 @@ if (*uc != 0) break; } - if (offset == fw->datasize) { + if (offset >= fw->datasize) { device_printf(sc->sc_dev, "firmware Boot Record Area not found\n"); error = EIO; @@ -1782,6 +1784,12 @@ bra_opt = (const struct upgt_fw_bra_option *)p; bra_option_type = le32toh(bra_opt->type); bra_option_len = le32toh(bra_opt->len) * sizeof(*uc); + + if (bra_option_len / sizeof(*uc) != le32toh(bra_opt->len)) { + device_printf(sc->sc_dev, "bra_option_len overflow\n"); + error = EINVAL; + goto fail; + } switch (bra_option_type) { case UPGT_BRA_TYPE_FW: