mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-25 07:29:24 -05:00
285 lines
10 KiB
Diff
285 lines
10 KiB
Diff
From 0273cba64b0436d481e09222a631a6acc274b96c Mon Sep 17 00:00:00 2001
|
|
From: Arif Hussain <c_arifh@qca.qualcomm.com>
|
|
Date: Tue, 7 Jan 2014 20:58:29 -0800
|
|
Subject: wlan: Fix ioctl copy issue
|
|
|
|
Few IOCTL's SET command's uses ODD number,
|
|
so we cannot utilize kernel facility "extra".
|
|
We need to copy the user data in kernel buffer
|
|
using copy_from_user function.
|
|
|
|
Change-Id: I550bf90fbbacb9d5ac4187ed423fca90fafccad1
|
|
CRs-Fixed: 596898
|
|
---
|
|
CORE/HDD/src/wlan_hdd_wext.c | 146 +++++++++++++++++++++++++++++++++++++------
|
|
1 file changed, 127 insertions(+), 19 deletions(-)
|
|
|
|
(limited to 'CORE/HDD/src/wlan_hdd_wext.c')
|
|
|
|
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
|
|
index 55b2100..90df277 100644
|
|
--- a/CORE/HDD/src/wlan_hdd_wext.c
|
|
+++ b/CORE/HDD/src/wlan_hdd_wext.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
|
|
*
|
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
|
*
|
|
@@ -373,6 +373,56 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest,
|
|
|
|
/**---------------------------------------------------------------------------
|
|
|
|
+ \brief mem_alloc_copy_from_user_helper -
|
|
+
|
|
+ Helper function to allocate buffer and copy user data.
|
|
+
|
|
+ \param - wrqu - Pointer to IOCTL Data.
|
|
+ len - size
|
|
+
|
|
+ \return - On Success pointer to buffer, On failure NULL
|
|
+
|
|
+ --------------------------------------------------------------------------*/
|
|
+static void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len)
|
|
+{
|
|
+ u8 *ptr = NULL;
|
|
+
|
|
+ /* in order to protect the code, an extra byte is post appended to the buffer
|
|
+ * and the null termination is added. However, when allocating (len+1) byte
|
|
+ * of memory, we need to make sure that there is no uint overflow when doing
|
|
+ * addition. In theory check len < UINT_MAX protects the uint overflow. For
|
|
+ * wlan private ioctl, the buffer size is much less than UINT_MAX, as a good
|
|
+ * guess, now, it is assumed that the private command buffer size is no
|
|
+ * greater than 4K (4096 bytes). So we use 4096 as the upper boundary for now.
|
|
+ */
|
|
+ if (len > MAX_USER_COMMAND_SIZE)
|
|
+ {
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
|
|
+ "Invalid length");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ ptr = kmalloc(len + 1, GFP_KERNEL);
|
|
+ if (NULL == ptr)
|
|
+ {
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
|
|
+ "unable to allocate memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (copy_from_user(ptr, wrqu_data, len))
|
|
+ {
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
|
|
+ "%s: failed to copy data to user buffer", __func__);
|
|
+ kfree(ptr);
|
|
+ return NULL;
|
|
+ }
|
|
+ ptr[len] = '\0';
|
|
+ return ptr;
|
|
+}
|
|
+
|
|
+/**---------------------------------------------------------------------------
|
|
+
|
|
\brief hdd_wlan_get_version() -
|
|
|
|
This function use to get Wlan Driver, Firmware, & Hardware Version.
|
|
@@ -4220,15 +4270,13 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in
|
|
VOS_STATUS vstatus;
|
|
int sub_cmd = wrqu->data.flags;
|
|
int ret = 0; /* success */
|
|
+ char *pBuffer = NULL;
|
|
hdd_adapter_t *pAdapter = (netdev_priv(dev));
|
|
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
|
|
#ifdef WLAN_FEATURE_VOWIFI
|
|
hdd_config_t *pConfig = pHddCtx->cfg_ini;
|
|
#endif /* WLAN_FEATURE_VOWIFI */
|
|
|
|
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received length %d", __func__, wrqu->data.length);
|
|
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received data %s", __func__, extra);
|
|
-
|
|
if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
|
|
{
|
|
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
|
|
@@ -4236,15 +4284,30 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in
|
|
return -EBUSY;
|
|
}
|
|
|
|
+ /* ODD number is used for set, copy data using copy_from_user */
|
|
+ pBuffer = mem_alloc_copy_from_user_helper(wrqu->data.pointer,
|
|
+ wrqu->data.length);
|
|
+ if (NULL == pBuffer)
|
|
+ {
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
|
|
+ "mem_alloc_copy_from_user_helper fail");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
|
|
+ "%s: Received length %d", __func__, wrqu->data.length);
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
|
|
+ "%s: Received data %s", __func__, pBuffer);
|
|
+
|
|
switch(sub_cmd)
|
|
{
|
|
case WE_WOWL_ADD_PTRN:
|
|
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "ADD_PTRN");
|
|
- hdd_add_wowl_ptrn(pAdapter, extra);
|
|
+ hdd_add_wowl_ptrn(pAdapter, pBuffer);
|
|
break;
|
|
case WE_WOWL_DEL_PTRN:
|
|
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "DEL_PTRN");
|
|
- hdd_del_wowl_ptrn(pAdapter, extra);
|
|
+ hdd_del_wowl_ptrn(pAdapter, pBuffer);
|
|
break;
|
|
#if defined WLAN_FEATURE_VOWIFI
|
|
case WE_NEIGHBOR_REPORT_REQUEST:
|
|
@@ -4259,7 +4322,7 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in
|
|
if( !neighborReq.no_ssid )
|
|
{
|
|
neighborReq.ssid.length = (wrqu->data.length - 1) > 32 ? 32 : (wrqu->data.length - 1) ;
|
|
- vos_mem_copy( neighborReq.ssid.ssId, extra, neighborReq.ssid.length );
|
|
+ vos_mem_copy( neighborReq.ssid.ssId, pBuffer, neighborReq.ssid.length );
|
|
}
|
|
|
|
callbackInfo.neighborRspCallback = NULL;
|
|
@@ -4277,10 +4340,10 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in
|
|
#endif
|
|
case WE_SET_AP_WPS_IE:
|
|
hddLog( LOGE, "Received WE_SET_AP_WPS_IE" );
|
|
- sme_updateP2pIe( WLAN_HDD_GET_HAL_CTX(pAdapter), extra, wrqu->data.length );
|
|
+ sme_updateP2pIe( WLAN_HDD_GET_HAL_CTX(pAdapter), pBuffer, wrqu->data.length );
|
|
break;
|
|
case WE_SET_CONFIG:
|
|
- vstatus = hdd_execute_config_command(pHddCtx, extra);
|
|
+ vstatus = hdd_execute_config_command(pHddCtx, pBuffer);
|
|
if (VOS_STATUS_SUCCESS != vstatus)
|
|
{
|
|
ret = -EINVAL;
|
|
@@ -4293,6 +4356,7 @@ static int iw_setchar_getnone(struct net_device *dev, struct iw_request_info *in
|
|
break;
|
|
}
|
|
}
|
|
+ kfree(pBuffer);
|
|
return ret;
|
|
}
|
|
|
|
@@ -5014,7 +5078,6 @@ int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info
|
|
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
|
tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
|
|
int sub_cmd = wrqu->data.flags;
|
|
- int *value = (int*)extra;
|
|
int apps_args[MAX_VAR_ARGS] = {0};
|
|
int num_args = wrqu->data.length;
|
|
hdd_station_ctx_t *pStaCtx = NULL ;
|
|
@@ -5035,7 +5098,14 @@ int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info
|
|
{
|
|
num_args = MAX_VAR_ARGS;
|
|
}
|
|
- vos_mem_copy(apps_args, value, (sizeof(int)) * num_args);
|
|
+
|
|
+ /* ODD number is used for set, copy data using copy_from_user */
|
|
+ if (copy_from_user(apps_args, wrqu->data.pointer, (sizeof(int)) * num_args))
|
|
+ {
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
|
|
+ "%s: failed to copy data to user buffer", __func__);
|
|
+ return -EFAULT;
|
|
+ }
|
|
|
|
if(( sub_cmd == WE_MCC_CONFIG_CREDENTIAL ) ||
|
|
(sub_cmd == WE_MCC_CONFIG_PARAMS ))
|
|
@@ -6377,9 +6447,23 @@ static int iw_set_packet_filter_params(struct net_device *dev, struct iw_request
|
|
union iwreq_data *wrqu, char *extra)
|
|
{
|
|
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
|
- tpPacketFilterCfg pRequest = (tpPacketFilterCfg) extra;
|
|
+ tpPacketFilterCfg pRequest = NULL;
|
|
+ int ret;
|
|
|
|
- return wlan_hdd_set_filter(WLAN_HDD_GET_CTX(pAdapter), pRequest, pAdapter->sessionId);
|
|
+ /* ODD number is used for set, copy data using copy_from_user */
|
|
+ pRequest = mem_alloc_copy_from_user_helper(wrqu->data.pointer,
|
|
+ wrqu->data.length);
|
|
+ if (NULL == pRequest)
|
|
+ {
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
|
|
+ "mem_alloc_copy_from_user_helper fail");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ ret = wlan_hdd_set_filter(WLAN_HDD_GET_CTX(pAdapter), pRequest, pAdapter->sessionId);
|
|
+ kfree(pRequest);
|
|
+
|
|
+ return ret;
|
|
}
|
|
#endif
|
|
static int iw_get_statistics(struct net_device *dev,
|
|
@@ -7053,10 +7137,10 @@ static int iw_set_band_config(struct net_device *dev,
|
|
union iwreq_data *wrqu, char *extra)
|
|
{
|
|
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
|
- tANI_U8 *ptr = extra;
|
|
+ tANI_U8 *ptr = NULL;
|
|
int ret = 0;
|
|
|
|
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: ", __func__);
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ", __func__);
|
|
|
|
if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
|
|
{
|
|
@@ -7065,23 +7149,47 @@ static int iw_set_band_config(struct net_device *dev,
|
|
return -EBUSY;
|
|
}
|
|
|
|
+ /* ODD number is used for set, copy data using copy_from_user */
|
|
+ ptr = mem_alloc_copy_from_user_helper(wrqu->data.pointer,
|
|
+ wrqu->data.length);
|
|
+ if (NULL == ptr)
|
|
+ {
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
|
|
+ "mem_alloc_copy_from_user_helper fail");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
if (memcmp(ptr, "SETBAND ", 8) == 0)
|
|
{
|
|
/* Change band request received */
|
|
ret = hdd_setBand_helper(dev, ptr);
|
|
- return ret;
|
|
-
|
|
}
|
|
- return 0;
|
|
+ kfree(ptr);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int iw_set_power_params_priv(struct net_device *dev,
|
|
struct iw_request_info *info,
|
|
union iwreq_data *wrqu, char *extra)
|
|
{
|
|
+ int ret;
|
|
+ char *ptr;
|
|
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
|
|
"Set power params Private");
|
|
- return iw_set_power_params(dev,info,wrqu,extra,0);
|
|
+ /* ODD number is used for set, copy data using copy_from_user */
|
|
+ ptr = mem_alloc_copy_from_user_helper(wrqu->data.pointer,
|
|
+ wrqu->data.length);
|
|
+ if (NULL == ptr)
|
|
+ {
|
|
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
|
|
+ "mem_alloc_copy_from_user_helper fail");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ ret = iw_set_power_params(dev, info, wrqu, ptr, 0);
|
|
+ kfree(ptr);
|
|
+ return ret;
|
|
}
|
|
|
|
|
|
--
|
|
cgit v1.1
|
|
|