aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryang-cy.chen <yang-cy.chen@mediatek.com>2016-03-18 19:25:27 +0800
committerMoyster <oysterized@gmail.com>2016-08-26 16:02:18 +0200
commit762f5b74c7428e76566cbaa4edba9c0afac53b6b (patch)
tree0aa54e7c988eb53fea0b2884867e5bb7ab316917
parentf5bb9a717fb164d134064c24a88038e126e36ea2 (diff)
downloadandroid_kernel_m2note-762f5b74c7428e76566cbaa4edba9c0afac53b6b.tar.gz
Security vulnerability in Mediatek Wifi driver
Problem: Security vulnerability of directly using user space pointer in kernel space Solution: Using copy_from_user and boundary protection to prevent such issue in kernel Bug num:27677942 Change-Id: I410171377fda5b841523d4b5a35d53baee2d35ab Signed-off-by: yang-cy.chen <yang-cy.chen@mediatek.com>
-rwxr-xr-x[-rw-r--r--]drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext.c13
-rwxr-xr-x[-rw-r--r--]drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext_priv.c48
2 files changed, 26 insertions, 35 deletions
diff --git a/drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext.c
index 99bf5c7bb..b1c3d2087 100644..100755
--- a/drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext.c
+++ b/drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext.c
@@ -462,7 +462,7 @@ const long channel_freq[] = {
#define NUM_CHANNELS (sizeof(channel_freq) / sizeof(channel_freq[0]))
#define MAX_SSID_LEN 32
-
+#define COUNTRY_CODE_LEN 10 /*country code length */
/*******************************************************************************
* D A T A T Y P E S
@@ -3917,7 +3917,7 @@ wext_set_country (
P_GLUE_INFO_T prGlueInfo;
WLAN_STATUS rStatus;
UINT_32 u4BufLen;
- UINT_8 aucCountry[2];
+ UINT_8 aucCountry[COUNTRY_CODE_LEN];
ASSERT(prNetDev);
@@ -3925,17 +3925,18 @@ wext_set_country (
* and "COUNTRY JP"
*/
if (FALSE == GLUE_CHK_PR2(prNetDev, iwr) ||
- !iwr->u.data.pointer || iwr->u.data.length < 10) {
+ !iwr->u.data.pointer || iwr->u.data.length != COUNTRY_CODE_LEN) {
return -EINVAL;
}
prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
- aucCountry[0] = *((PUINT_8)iwr->u.data.pointer + 8);
- aucCountry[1] = *((PUINT_8)iwr->u.data.pointer + 9);
+ if (copy_from_user(aucCountry, iwr->u.data.pointer, COUNTRY_CODE_LEN)) {
+ return -EFAULT;
+ }
rStatus = kalIoctl(prGlueInfo,
wlanoidSetCountryCode,
- &aucCountry[0],
+ &aucCountry[COUNTRY_CODE_LEN - 2],
2,
FALSE,
FALSE,
diff --git a/drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext_priv.c b/drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext_priv.c
index 32420ed8d..d3547a90e 100644..100755
--- a/drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext_priv.c
+++ b/drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext_priv.c
@@ -1642,11 +1642,13 @@ priv_set_ints (
IN char *pcExtra
)
{
- UINT_32 u4SubCmd, u4BufLen;
+ UINT_32 u4SubCmd, u4BufLen, u4CmdLen;
P_GLUE_INFO_T prGlueInfo;
int status = 0;
WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
P_SET_TXPWR_CTRL_T prTxpwr;
+ UINT_16 i = 0;
+ INT_32 setting[4] = {0};
ASSERT(prNetDev);
ASSERT(prIwReqInfo);
@@ -1659,19 +1661,16 @@ priv_set_ints (
prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
u4SubCmd = (UINT_32) prIwReqData->data.flags;
+ u4CmdLen = prIwReqData->data.length;
switch (u4SubCmd) {
case PRIV_CMD_SET_TX_POWER:
{
- INT_32 *setting = prIwReqData->data.pointer;
- UINT_16 i;
-
-#if 0
- printk("Tx power num = %d\n", prIwReqData->data.length);
+ if (u4CmdLen > 4)
+ return -EINVAL;
+ if (copy_from_user(setting, prIwReqData->data.pointer, u4CmdLen))
+ return -EFAULT;
- printk("Tx power setting = %d %d %d %d\n",
- setting[0], setting[1], setting[2], setting[3]);
-#endif
prTxpwr = &prGlueInfo->rTxPwr;
if (setting[0] == 0 && prIwReqData->data.length == 4 /* argc num */) {
/* 0 (All networks), 1 (legacy STA), 2 (Hotspot AP), 3 (P2P), 4 (BT over Wi-Fi) */
@@ -1993,7 +1992,6 @@ priv_set_struct (
break;
case PRIV_CMD_SW_CTRL:
- pu4IntBuf = (PUINT_32)prIwReqData->data.pointer;
u4CmdLen = prIwReqData->data.length;
prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0];
@@ -2002,7 +2000,6 @@ priv_set_struct (
return -EINVAL;
}
- //kalMemCopy(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, 8);
if (copy_from_user(&prNdisReq->ndisOidContent[0],
prIwReqData->data.pointer,
u4CmdLen)) {
@@ -2121,9 +2118,7 @@ priv_get_struct (
break;
case PRIV_CMD_SW_CTRL:
- pu4IntBuf = (PUINT_32)prIwReqData->data.pointer;
prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0];
-
u4CopyDataMax = sizeof(aucOidBuf) - OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent);
if ((prIwReqData->data.length>u4CopyDataMax)
|| copy_from_user(&prNdisReq->ndisOidContent[0],
@@ -2627,10 +2622,10 @@ priv_set_string(
)
{
P_GLUE_INFO_T GlueInfo;
- INT_32 Status;
+ INT_32 Status = 0;
UINT_32 Subcmd;
- UINT_8 *InBuf;
- UINT_32 InBufLen;
+ UINT_8 *InBuf = aucOidBuf;
+ UINT_32 BufLen;
/* sanity check */
@@ -2639,29 +2634,24 @@ priv_set_string(
ASSERT(prIwReqData);
ASSERT(pcExtra);
- /* init */
- DBGLOG(REQ, INFO, ("priv_set_string (%s)(%d)\n",
- (UINT8 *)prIwReqData->data.pointer, (INT32)prIwReqData->data.length));
-
if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) {
return -EINVAL;
}
- GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
- InBuf = aucOidBuf;
- InBufLen = prIwReqData->data.length;
- Status = 0;
+ BufLen = prIwReqData->data.length;
+ DBGLOG(REQ, INFO, ("priv_set_string (%ld)\n", BufLen));
+ GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
- if (InBufLen > CMD_OID_BUF_LENGTH) {
- DBGLOG(REQ, ERROR, ("Input data length is invalid %ld\n", InBufLen));
+ if (BufLen > CMD_OID_BUF_LENGTH) {
+ DBGLOG(REQ, ERROR, ("Input data length is invalid %ld\n", BufLen));
return -EINVAL;
}
- if (copy_from_user(InBuf, prIwReqData->data.pointer, InBufLen)) {
+ if (copy_from_user(InBuf, prIwReqData->data.pointer, BufLen)) {
return -EFAULT;
}
- Subcmd = CmdStringDecParse(prIwReqData->data.pointer, &InBuf, &InBufLen);
+ Subcmd = CmdStringDecParse(InBuf, &InBuf, &BufLen);
DBGLOG(REQ, INFO, ("priv_set_string> command = %u\n", (UINT32)Subcmd));
/* handle the command */
@@ -2669,7 +2659,7 @@ priv_set_string(
{
#if (CFG_SUPPORT_TDLS == 1)
case PRIV_CMD_OTHER_TDLS:
- TdlsexCmd(GlueInfo, InBuf, InBufLen);
+ TdlsexCmd(GlueInfo, InBuf, BufLen);
break;
#endif /* CFG_SUPPORT_TDLS */