diff options
| author | yang-cy.chen <yang-cy.chen@mediatek.com> | 2016-03-18 19:25:27 +0800 |
|---|---|---|
| committer | Moyster <oysterized@gmail.com> | 2016-08-26 16:02:18 +0200 |
| commit | 762f5b74c7428e76566cbaa4edba9c0afac53b6b (patch) | |
| tree | 0aa54e7c988eb53fea0b2884867e5bb7ab316917 | |
| parent | f5bb9a717fb164d134064c24a88038e126e36ea2 (diff) | |
| download | android_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.c | 13 | ||||
| -rwxr-xr-x[-rw-r--r--] | drivers/misc/mediatek/connectivity/conn_soc/drv_wlan/mt_wifi/wlan/os/linux/gl_wext_priv.c | 48 |
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 */ |
