From b0ca42f68a25d3e3f4541411925f8fb837a3cdd0 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 3 Nov 2010 16:08:25 -0700 Subject: [PATCH] net: wireless: bcm4329: Check for out of bounds in scan results parsing Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcm4329/wl_iw.c | 51 ++++++++++++---------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 66d8d2b54aa8..6d83a259bf95 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -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; -- 2.34.1