Author: hselasky
Date: Mon Feb 18 17:55:27 2013
New Revision: 246944
URL: http://svnweb.freebsd.org/changeset/base/246944

Log:
  Fix bad EEPROM parsing code.
  
  MFC after:    2 weeks

Modified:
  head/sys/dev/usb/wlan/if_upgt.c
  head/sys/dev/usb/wlan/if_upgtvar.h

Modified: head/sys/dev/usb/wlan/if_upgt.c
==============================================================================
--- head/sys/dev/usb/wlan/if_upgt.c     Mon Feb 18 16:19:26 2013        
(r246943)
+++ head/sys/dev/usb/wlan/if_upgt.c     Mon Feb 18 17:55:27 2013        
(r246944)
@@ -1132,12 +1132,23 @@ upgt_eeprom_parse(struct upgt_softc *sc)
            (sizeof(struct upgt_eeprom_header) + preamble_len));
 
        while (!option_end) {
+
+               /* sanity check */
+               if (eeprom_option >= (struct upgt_eeprom_option *)
+                   (sc->sc_eeprom + UPGT_EEPROM_SIZE)) {
+                       return (EINVAL);
+               }
+
                /* the eeprom option length is stored in words */
                option_len =
                    (le16toh(eeprom_option->len) - 1) * sizeof(uint16_t);
                option_type =
                    le16toh(eeprom_option->type);
 
+               /* sanity check */
+               if (option_len == 0 || option_len >= UPGT_EEPROM_SIZE)
+                       return (EINVAL);
+
                switch (option_type) {
                case UPGT_EEPROM_TYPE_NAME:
                        DPRINTF(sc, UPGT_DEBUG_FW,
@@ -1208,7 +1219,6 @@ upgt_eeprom_parse(struct upgt_softc *sc)
                eeprom_option = (struct upgt_eeprom_option *)
                    (eeprom_option->data + option_len);
        }
-
        return (0);
 }
 
@@ -1217,7 +1227,9 @@ upgt_eeprom_parse_freq3(struct upgt_soft
 {
        struct upgt_eeprom_freq3_header *freq3_header;
        struct upgt_lmac_freq3 *freq3;
-       int i, elements, flags;
+       int i;
+       int elements;
+       int flags;
        unsigned channel;
 
        freq3_header = (struct upgt_eeprom_freq3_header *)data;
@@ -1229,6 +1241,9 @@ upgt_eeprom_parse_freq3(struct upgt_soft
        DPRINTF(sc, UPGT_DEBUG_FW, "flags=0x%02x elements=%d\n",
            flags, elements);
 
+       if (elements >= (int)(UPGT_EEPROM_SIZE / sizeof(freq3[0])))
+               return;
+
        for (i = 0; i < elements; i++) {
                channel = ieee80211_mhz2ieee(le16toh(freq3[i].freq), 0);
                if (channel >= IEEE80211_CHAN_MAX)
@@ -1247,7 +1262,11 @@ upgt_eeprom_parse_freq4(struct upgt_soft
        struct upgt_eeprom_freq4_header *freq4_header;
        struct upgt_eeprom_freq4_1 *freq4_1;
        struct upgt_eeprom_freq4_2 *freq4_2;
-       int i, j, elements, settings, flags;
+       int i;
+       int j;
+       int elements;
+       int settings;
+       int flags;
        unsigned channel;
 
        freq4_header = (struct upgt_eeprom_freq4_header *)data;
@@ -1262,6 +1281,9 @@ upgt_eeprom_parse_freq4(struct upgt_soft
        DPRINTF(sc, UPGT_DEBUG_FW, "flags=0x%02x elements=%d settings=%d\n",
            flags, elements, settings);
 
+       if (elements >= (int)(UPGT_EEPROM_SIZE / sizeof(freq4_1[0])))
+               return;
+
        for (i = 0; i < elements; i++) {
                channel = ieee80211_mhz2ieee(le16toh(freq4_1[i].freq), 0);
                if (channel >= IEEE80211_CHAN_MAX)
@@ -1282,7 +1304,8 @@ void
 upgt_eeprom_parse_freq6(struct upgt_softc *sc, uint8_t *data, int len)
 {
        struct upgt_lmac_freq6 *freq6;
-       int i, elements;
+       int i;
+       int elements;
        unsigned channel;
 
        freq6 = (struct upgt_lmac_freq6 *)data;
@@ -1290,6 +1313,9 @@ upgt_eeprom_parse_freq6(struct upgt_soft
 
        DPRINTF(sc, UPGT_DEBUG_FW, "elements=%d\n", elements);
 
+       if (elements >= (int)(UPGT_EEPROM_SIZE / sizeof(freq6[0])))
+               return;
+
        for (i = 0; i < elements; i++) {
                channel = ieee80211_mhz2ieee(le16toh(freq6[i].freq), 0);
                if (channel >= IEEE80211_CHAN_MAX)

Modified: head/sys/dev/usb/wlan/if_upgtvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_upgtvar.h  Mon Feb 18 16:19:26 2013        
(r246943)
+++ head/sys/dev/usb/wlan/if_upgtvar.h  Mon Feb 18 17:55:27 2013        
(r246944)
@@ -453,7 +453,7 @@ struct upgt_softc {
        struct upgt_memory       sc_memory;
 
        /* data which we found in the EEPROM */
-       uint8_t                  sc_eeprom[UPGT_EEPROM_SIZE];
+       uint8_t                  sc_eeprom[2 * UPGT_EEPROM_SIZE] __aligned(4);
        uint16_t                 sc_eeprom_hwrx;
        struct upgt_lmac_freq3   sc_eeprom_freq3[IEEE80211_CHAN_MAX];
        struct upgt_lmac_freq4   sc_eeprom_freq4[IEEE80211_CHAN_MAX][8];
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to