wlan: DroidSec string validation issues
1. the total_len is a user controlled parameter, an attacker
could pass total_len as a huge number and driver may result in
heap based overflow. Fix is to add MAX_LEN check and the value of
4096 is based on wpa_supplicant max data
2. while reading strings using sscanf buffers are allocated with
32 bytes and sscanf %32s could write 32 bytes and automatically
add a NUL termination. which could result in buffer overflow.
Fix is to read only 31 bytes and keep 1 byte for '\0'
CRs-Fixed: 594924
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
old mode 100755
new mode 100644
index 4d836eb..c070a7a
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -189,6 +189,8 @@
tCsrCcxBeaconReq *pCcxBcnReq);
#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
+#define WLAN_PRIV_DATA_MAX_LEN 4096
+
/*
* Driver miracast parameters 0-Disabled
* 1-Source, 2-Sink
@@ -1663,7 +1665,8 @@
goto exit;
}
- if (priv_data.total_len <= 0)
+ if (priv_data.total_len <= 0 ||
+ priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
"%s:invalid priv_data.total_len(%d)!!!", __func__,
@@ -3769,7 +3772,7 @@
if ('\0' == *inPtr) return -EINVAL;
/*getting the first argument ie measurement token*/
- v = sscanf(inPtr, "%32s ", buf);
+ v = sscanf(inPtr, "%31s ", buf);
if (1 != v) return -EINVAL;
v = kstrtos32(buf, 10, &tempInt);
@@ -3795,7 +3798,7 @@
/*no ie data after the number of ie fields argument and spaces*/
if ( '\0' == *inPtr ) return -EINVAL;
- v = sscanf(inPtr, "%32s ", buf);
+ v = sscanf(inPtr, "%31s ", buf);
if (1 != v) return -EINVAL;
v = kstrtos32(buf, 10, &tempInt);
@@ -4055,8 +4058,8 @@
int v = 0;
tANI_U8 tempBuf[32];
tANI_U8 tempByte = 0;
- /* 12 hexa decimal digits and 5 ':' */
- tANI_U8 macAddress[17];
+ /* 12 hexa decimal digits, 5 ':' and '\0' */
+ tANI_U8 macAddress[18];
inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
/*no argument after the command*/
@@ -4110,7 +4113,7 @@
}
/*getting the next argument ie the channel number */
- v = sscanf(inPtr, "%32s ", tempBuf);
+ v = sscanf(inPtr, "%31s ", tempBuf);
if (1 != v) return -EINVAL;
v = kstrtos32(tempBuf, 10, &tempInt);
@@ -4133,7 +4136,7 @@
}
/*getting the next argument ie the dwell time */
- v = sscanf(inPtr, "%32s ", tempBuf);
+ v = sscanf(inPtr, "%31s ", tempBuf);
if (1 != v) return -EINVAL;
v = kstrtos32(tempBuf, 10, &tempInt);
@@ -4248,7 +4251,7 @@
}
/*getting the first argument ie the number of channels*/
- v = sscanf(inPtr, "%32s ", buf);
+ v = sscanf(inPtr, "%31s ", buf);
if (1 != v) return -EINVAL;
v = kstrtos32(buf, 10, &tempInt);
@@ -4299,7 +4302,7 @@
}
}
- v = sscanf(inPtr, "%32s ", buf);
+ v = sscanf(inPtr, "%31s ", buf);
if (1 != v) return -EINVAL;
v = kstrtos32(buf, 10, &tempInt);
@@ -4341,8 +4344,8 @@
int tempInt;
int v = 0;
tANI_U8 tempBuf[32];
- /* 12 hexa decimal digits and 5 ':' */
- tANI_U8 macAddress[17];
+ /* 12 hexa decimal digits, 5 ':' and '\0' */
+ tANI_U8 macAddress[18];
inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
/*no argument after the command*/
@@ -4396,7 +4399,7 @@
}
/*getting the next argument ie the channel number */
- v = sscanf(inPtr, "%32s ", tempBuf);
+ v = sscanf(inPtr, "%31s ", tempBuf);
if (1 != v) return -EINVAL;
v = kstrtos32(tempBuf, 10, &tempInt);