From 28d4f0c1f712bffb4aa5b47f06e97d5a9fa06d29 Mon Sep 17 00:00:00 2001 From: Arif Hussain Date: Sun, 27 Oct 2013 23:01:14 -0700 Subject: wlan: Userspace data copy fix Use copy_to_user and copy_from_user for copying data to/from user space. Change-Id: I07ed5361b439f4bcd61bbf693cc17c950f5b2660 CRs-Fixed: 561022 --- CORE/HDD/inc/wlan_hdd_main.h | 1 + CORE/HDD/src/wlan_hdd_hostapd.c | 160 ++++++++++++++++++++++++++++++---------- 2 files changed, 124 insertions(+), 37 deletions(-) diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 57b2ec0..e3fcca4 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -153,6 +153,7 @@ #define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] /** Mac Address string **/ #define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ADDRESS_STR_LEN 18 /* Including null terminator */ #define MAX_GENIE_LEN 255 #define WLAN_CHIP_VERSION "WCNSS" diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c index a5d696e..a155932 100644 --- a/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/CORE/HDD/src/wlan_hdd_hostapd.c @@ -1418,12 +1418,13 @@ static iw_softap_getassoc_stamacaddr(struct net_device *dev, union iwreq_data *wrqu, char *extra) { hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); - unsigned char *pmaclist; + unsigned int maclist_index; hdd_station_info_t *pStaInfo = pHostapdAdapter->aStaInfo; + char maclist_null = '\0'; int cnt = 0, len; - pmaclist = wrqu->data.pointer + sizeof(unsigned long int); + maclist_index = sizeof(unsigned long int); len = wrqu->data.length; spin_lock_bh( &pHostapdAdapter->staInfo_lock ); @@ -1431,8 +1432,13 @@ static iw_softap_getassoc_stamacaddr(struct net_device *dev, if (TRUE == pStaInfo[cnt].isUsed) { if(!IS_BROADCAST_MAC(pStaInfo[cnt].macAddrSTA.bytes)) { - memcpy((void *)pmaclist, (void *)&(pStaInfo[cnt].macAddrSTA), sizeof(v_MACADDR_t)); - pmaclist += sizeof(v_MACADDR_t); + if (copy_to_user((void *)wrqu->data.pointer + maclist_index, + (void *)&(pStaInfo[cnt].macAddrSTA), sizeof(v_MACADDR_t))) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + return -EFAULT; + } + maclist_index += sizeof(v_MACADDR_t); len -= sizeof(v_MACADDR_t); } } @@ -1440,12 +1446,16 @@ static iw_softap_getassoc_stamacaddr(struct net_device *dev, } spin_unlock_bh( &pHostapdAdapter->staInfo_lock ); - *pmaclist = '\0'; - + if (copy_to_user((void *)wrqu->data.pointer + maclist_index, + (void *)&maclist_null, sizeof(maclist_null)) || + copy_to_user((void *)wrqu->data.pointer, + (void *)&wrqu->data.length, sizeof(wrqu->data.length))) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + return -EFAULT; + } wrqu->data.length -= len; - *(unsigned long int *)(wrqu->data.pointer) = wrqu->data.length; - return 0; } @@ -1494,20 +1504,35 @@ static iw_softap_ap_stats(struct net_device *dev, int len = wrqu->data.length; pstatbuf = wrqu->data.pointer; - WLANSAP_GetStatistics((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, &statBuffer, (v_BOOL_t)wrqu->data.flags); - - len = scnprintf(pstatbuf, len, - "RUF=%d RMF=%d RBF=%d " - "RUB=%d RMB=%d RBB=%d " - "TUF=%d TMF=%d TBF=%d " - "TUB=%d TMB=%d TBB=%d", - (int)statBuffer.rxUCFcnt, (int)statBuffer.rxMCFcnt, (int)statBuffer.rxBCFcnt, - (int)statBuffer.rxUCBcnt, (int)statBuffer.rxMCBcnt, (int)statBuffer.rxBCBcnt, - (int)statBuffer.txUCFcnt, (int)statBuffer.txMCFcnt, (int)statBuffer.txBCFcnt, - (int)statBuffer.txUCBcnt, (int)statBuffer.txMCBcnt, (int)statBuffer.txBCBcnt - ); + WLANSAP_GetStatistics((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, + &statBuffer, (v_BOOL_t)wrqu->data.flags); + pstatbuf = kmalloc(wrqu->data.length, GFP_KERNEL); + if(NULL == pstatbuf) { + hddLog(LOG1, "unable to allocate memory"); + return -ENOMEM; + } + len = scnprintf(pstatbuf, wrqu->data.length, + "RUF=%d RMF=%d RBF=%d " + "RUB=%d RMB=%d RBB=%d " + "TUF=%d TMF=%d TBF=%d " + "TUB=%d TMB=%d TBB=%d", + (int)statBuffer.rxUCFcnt, (int)statBuffer.rxMCFcnt, + (int)statBuffer.rxBCFcnt, (int)statBuffer.rxUCBcnt, + (int)statBuffer.rxMCBcnt, (int)statBuffer.rxBCBcnt, + (int)statBuffer.txUCFcnt, (int)statBuffer.txMCFcnt, + (int)statBuffer.txBCFcnt, (int)statBuffer.txUCBcnt, + (int)statBuffer.txMCBcnt, (int)statBuffer.txBCBcnt); + + if (len > wrqu->data.length || + copy_to_user((void *)wrqu->data.pointer, (void *)pstatbuf, len)) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + kfree(pstatbuf); + return -EFAULT; + } wrqu->data.length -= len; + kfree(pstatbuf); return 0; } @@ -1870,8 +1895,15 @@ int iw_get_genie(struct net_device *dev, status = WLANSap_getstationIE_information(pVosContext, &length, genIeBytes); - wrqu->data.length = VOS_MIN((u_int16_t) length, DOT11F_IE_RSN_MAX_LEN); - vos_mem_copy( wrqu->data.pointer, (v_VOID_t*)genIeBytes, wrqu->data.length); + length = VOS_MIN((u_int16_t) length, DOT11F_IE_RSN_MAX_LEN); + if (wrqu->data.length < length || + copy_to_user(wrqu->data.pointer, + (v_VOID_t*)genIeBytes, length)) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + return -EFAULT; + } + wrqu->data.length = length; hddLog(LOG1,FL(" RSN IE of %d bytes returned\n"), wrqu->data.length ); @@ -1885,18 +1917,30 @@ int iw_get_WPSPBCProbeReqIEs(struct net_device *dev, union iwreq_data *wrqu, char *extra) { hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); - sQcSapreq_WPSPBCProbeReqIES_t *pWPSPBCProbeReqIEs; + sQcSapreq_WPSPBCProbeReqIES_t WPSPBCProbeReqIEs; hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter); ENTER(); - + hddLog(LOG1,FL("get_WPSPBCProbeReqIEs ioctl\n")); - - pWPSPBCProbeReqIEs = (sQcSapreq_WPSPBCProbeReqIES_t *)(wrqu->data.pointer); - pWPSPBCProbeReqIEs->probeReqIELen = pHddApCtx->WPSPBCProbeReq.probeReqIELen; - vos_mem_copy(pWPSPBCProbeReqIEs->probeReqIE, pHddApCtx->WPSPBCProbeReq.probeReqIE, pWPSPBCProbeReqIEs->probeReqIELen); - vos_mem_copy(pWPSPBCProbeReqIEs->macaddr, pHddApCtx->WPSPBCProbeReq.peerMacAddr, sizeof(v_MACADDR_t)); - wrqu->data.length = 12 + pWPSPBCProbeReqIEs->probeReqIELen; - hddLog(LOG1, FL("Macaddress : "MAC_ADDRESS_STR"\n"), MAC_ADDR_ARRAY(pWPSPBCProbeReqIEs->macaddr)); + memset((void*)&WPSPBCProbeReqIEs, 0, sizeof(WPSPBCProbeReqIEs)); + + WPSPBCProbeReqIEs.probeReqIELen = pHddApCtx->WPSPBCProbeReq.probeReqIELen; + vos_mem_copy(&WPSPBCProbeReqIEs.probeReqIE, + pHddApCtx->WPSPBCProbeReq.probeReqIE, + WPSPBCProbeReqIEs.probeReqIELen); + vos_mem_copy(&WPSPBCProbeReqIEs.macaddr, + pHddApCtx->WPSPBCProbeReq.peerMacAddr, + sizeof(v_MACADDR_t)); + if (copy_to_user(wrqu->data.pointer, + (void *)&WPSPBCProbeReqIEs, + sizeof(WPSPBCProbeReqIEs))) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + return -EFAULT; + } + wrqu->data.length = 12 + WPSPBCProbeReqIEs.probeReqIELen; + hddLog(LOG1, FL("Macaddress : "MAC_ADDRESS_STR"\n"), + MAC_ADDR_ARRAY(WPSPBCProbeReqIEs.macaddr)); up(&pHddApCtx->semWpsPBCOverlapInd); EXIT(); return 0; @@ -2282,20 +2326,37 @@ static int iw_softap_setwpsie(struct net_device *dev, v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext; hdd_hostapd_state_t *pHostapdState; eHalStatus halStatus= eHAL_STATUS_SUCCESS; - u_int8_t *wps_genie = wrqu->data.pointer; + u_int8_t *wps_genie; + u_int8_t *fwps_genie; u_int8_t *pos; tpSap_WPSIE pSap_WPSIe; u_int8_t WPSIeType; u_int16_t length; ENTER(); - if(!wrqu->data.length) + if(!wrqu->data.length || wrqu->data.length <= QCSAP_MAX_WSC_IE) return 0; + wps_genie = kmalloc(wrqu->data.length, GFP_KERNEL); + + if(NULL == wps_genie) { + hddLog(LOG1, "unable to allocate memory"); + return -ENOMEM; + } + fwps_genie = wps_genie; + if (copy_from_user((void *)wps_genie, + wrqu->data.pointer, wrqu->data.length)) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + kfree(fwps_genie); + return -EFAULT; + } + pSap_WPSIe = vos_mem_malloc(sizeof(tSap_WPSIE)); if (NULL == pSap_WPSIe) { hddLog(LOGE, "VOS unable to allocate memory\n"); + kfree(fwps_genie); return -ENOMEM; } vos_mem_zero(pSap_WPSIe, sizeof(tSap_WPSIE)); @@ -2312,6 +2373,7 @@ static int iw_softap_setwpsie(struct net_device *dev, if (wps_genie[1] < 2 + 4) { vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); return -EINVAL; } else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) @@ -2385,6 +2447,7 @@ static int iw_softap_setwpsie(struct net_device *dev, default: hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)\n", (*pos<<8 | *(pos+1))); vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); return -EINVAL; } } @@ -2398,6 +2461,7 @@ static int iw_softap_setwpsie(struct net_device *dev, default: hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, wps_genie[0]); vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); return 0; } } @@ -2411,6 +2475,7 @@ static int iw_softap_setwpsie(struct net_device *dev, if (wps_genie[1] < 2 + 4) { vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); return -EINVAL; } else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) @@ -2575,6 +2640,7 @@ static int iw_softap_setwpsie(struct net_device *dev, } vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); EXIT(); return halStatus; } @@ -2682,7 +2748,7 @@ static int iw_set_ap_genie(struct net_device *dev, hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext; eHalStatus halStatus= eHAL_STATUS_SUCCESS; - u_int8_t *genie = wrqu->data.pointer; + u_int8_t *genie = (u_int8_t *)extra; ENTER(); @@ -2691,7 +2757,7 @@ static int iw_set_ap_genie(struct net_device *dev, EXIT(); return 0; } - + switch (genie[0]) { case DOT11F_EID_WPA: @@ -2702,7 +2768,7 @@ static int iw_set_ap_genie(struct net_device *dev, hdd_softap_Register_BC_STA(pHostapdAdapter, 1); } (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = 1; - halStatus = WLANSAP_Set_WPARSNIes(pVosContext, wrqu->data.pointer, wrqu->data.length); + halStatus = WLANSAP_Set_WPARSNIes(pVosContext, genie, wrqu->data.length); break; default: @@ -2768,6 +2834,7 @@ int iw_get_softap_linkspeed(struct net_device *dev, hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); hdd_context_t *pHddCtx; char *pLinkSpeed = (char*)extra; + char *pmacAddress; v_U32_t link_speed; unsigned short staId; int len = sizeof(v_U32_t)+1; @@ -2786,7 +2853,26 @@ int iw_get_softap_linkspeed(struct net_device *dev, } hddLog(VOS_TRACE_LEVEL_INFO, "%s wrqu->data.length= %d\n", __func__, wrqu->data.length); - status = hdd_string_to_hex ((char *)wrqu->data.pointer, wrqu->data.length, macAddress ); + if (wrqu->data.length != MAC_ADDRESS_STR_LEN) + { + hddLog(LOG1, "Invalid length"); + return -EINVAL; + } + pmacAddress = kmalloc(MAC_ADDRESS_STR_LEN, GFP_KERNEL); + if(NULL == pmacAddress) { + hddLog(LOG1, "unable to allocate memory"); + return -ENOMEM; + } + if (copy_from_user((void *)pmacAddress, + wrqu->data.pointer, wrqu->data.length)) + { + hddLog(LOG1, "%s: failed to copy data to user buffer", __func__); + kfree(pmacAddress); + return -EFAULT; + } + + status = hdd_string_to_hex (pmacAddress, wrqu->data.length, macAddress ); + kfree(pmacAddress); if (!VOS_IS_STATUS_SUCCESS(status )) { -- cgit v1.1