net: wireless: bcm4329: Check for out of bounds in scan results parsing
authorDmitry Shmidt <dimitrysh@google.com>
Wed, 3 Nov 2010 23:08:25 +0000 (16:08 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Wed, 3 Nov 2010 23:08:25 +0000 (16:08 -0700)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcm4329/wl_iw.c

index 66d8d2b54aa842f0af6efd26b6479c0e8f0219a8..6d83a259bf95c912850561bb542e62dfa149a8b9 100644 (file)
@@ -2525,7 +2525,7 @@ wl_iw_get_aplist(
        list->version = dtoh32(list->version);
        list->count = dtoh32(list->count);
        if (list->version != WL_BSS_INFO_VERSION) {
-               WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
+               WL_ERROR(("%s: list->version %d != WL_BSS_INFO_VERSION\n", \
                         __FUNCTION__, list->version));
                kfree(list);
                return -EINVAL;
@@ -2533,21 +2533,21 @@ wl_iw_get_aplist(
 
        for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
                bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
-               ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
-                       buflen));
+               if ((uintptr)bi >= ((uintptr)list + buflen)) {
+                       WL_ERROR(("%s: Scan results out of bounds\n",__FUNCTION__));
+                       kfree(list);
+                       return -E2BIG;
+               }
 
-               
                if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
                        continue;
 
-               
                memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
                addr[dwrq->length].sa_family = ARPHRD_ETHER;
                qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
                qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
                qual[dwrq->length].noise = 0x100 + bi->phy_noise;
 
-               
 #if WIRELESS_EXT > 18
                qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
 #else
@@ -2610,21 +2610,20 @@ wl_iw_iscan_get_aplist(
                for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
                        bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length))
                                  : list->bss_info;
-                       ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
-                               WLC_IW_ISCAN_MAXLEN));
+                       if ((uintptr)bi >= ((uintptr)list + WLC_IW_ISCAN_MAXLEN)) {
+                               WL_ERROR(("%s: Scan results out of bounds\n",__FUNCTION__));
+                               return -E2BIG;
+                       }
 
-                       
                        if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
                                continue;
 
-                       
                        memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
                        addr[dwrq->length].sa_family = ARPHRD_ETHER;
                        qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
                        qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
                        qual[dwrq->length].noise = 0x100 + bi->phy_noise;
 
-                       
 #if WIRELESS_EXT > 18
                        qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
 #else
@@ -3547,7 +3546,10 @@ wl_iw_get_scan_prep(
        int     ret = 0;
        int channel;
 
-       ASSERT(list);
+       if (!list) {
+               WL_ERROR(("%s: Null list pointer",__FUNCTION__));
+               return -EINVAL;
+       }
 
        for (i = 0; i < list->count && i < IW_MAX_AP; i++)
        {
@@ -3555,7 +3557,7 @@ wl_iw_get_scan_prep(
                        WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
                                __FUNCTION__, list->version));
                        return ret;
-                }
+               }
 
                bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
 
@@ -3571,7 +3573,6 @@ wl_iw_get_scan_prep(
                iwe.u.data.flags = 1;
                event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
 
-               
                if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
                        iwe.cmd = SIOCGIWMODE;
                        if (dtoh16(bi->capability) & DOT11_CAP_ESS)
@@ -3581,7 +3582,6 @@ wl_iw_get_scan_prep(
                        event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
                }
 
-               
                iwe.cmd = SIOCGIWFREQ;
                channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
                iwe.u.freq.m = wf_channel2mhz(channel,
@@ -3590,7 +3590,6 @@ wl_iw_get_scan_prep(
                iwe.u.freq.e = 6;
                event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
 
-               
                iwe.cmd = IWEVQUAL;
                iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
                iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
@@ -3607,7 +3606,6 @@ wl_iw_get_scan_prep(
                iwe.u.data.length = 0;
                event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
 
-               
                if (bi->rateset.count) {
                        if (((event -extra) + IW_EV_LCP_LEN) <= (uintptr)end) {
                                value = event + IW_EV_LCP_LEN;
@@ -3899,26 +3897,26 @@ wl_iw_iscan_get_scan(
            bi = NULL;
            for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
                bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
-               ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
-                       WLC_IW_ISCAN_MAXLEN));
 
-               
+               if ((uintptr)bi >= ((uintptr)list + WLC_IW_ISCAN_MAXLEN)) {
+                       WL_ERROR(("%s: Scan results out of bounds\n",__FUNCTION__));
+                       return -E2BIG;
+               }
+
                if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
                        IW_EV_QUAL_LEN >= end)
                        return -E2BIG;
-               
+
                iwe.cmd = SIOCGIWAP;
                iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
                memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
                event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
 
-               
                iwe.u.data.length = dtoh32(bi->SSID_len);
                iwe.cmd = SIOCGIWESSID;
                iwe.u.data.flags = 1;
                event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
 
-               
                if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
                        iwe.cmd = SIOCGIWMODE;
                        if (dtoh16(bi->capability) & DOT11_CAP_ESS)
@@ -3928,7 +3926,6 @@ wl_iw_iscan_get_scan(
                        event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
                }
 
-               
                iwe.cmd = SIOCGIWFREQ;
                channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
                iwe.u.freq.m = wf_channel2mhz(channel,
@@ -3937,17 +3934,14 @@ wl_iw_iscan_get_scan(
                iwe.u.freq.e = 6;
                event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
 
-               
                iwe.cmd = IWEVQUAL;
                iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
                iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
                iwe.u.qual.noise = 0x100 + bi->phy_noise;
                event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
 
-               
                wl_iw_handle_scanresults_ies(&event, end, info, bi);
 
-               
                iwe.cmd = SIOCGIWENCODE;
                if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
                        iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
@@ -3956,7 +3950,6 @@ wl_iw_iscan_get_scan(
                iwe.u.data.length = 0;
                event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
 
-               
                if (bi->rateset.count) {
                        if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
                                return -E2BIG;
@@ -5495,7 +5488,6 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
                p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16);
        }
 
-       
        iscan->iscan_ex_params_p->params.channel_num = \
                htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
                                        (nchan & WL_SCAN_PARAMS_COUNT_MASK));
@@ -5504,7 +5496,6 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
        (uint)((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) & \
                               WL_SCAN_PARAMS_COUNT_MASK);
 
-       
        params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t));
        iscan->iscan_ex_param_size = params_size;