summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Girigowda <sgirigow@codeaurora.org>2016-08-26 18:53:47 -0700
committerqcabuildsw <qcabuildsw@localhost>2016-10-17 21:53:07 -0700
commit1efc80ea4683e911bb378da44353f38d755da111 (patch)
tree9000357d6d474031041f1cde1f667e7b4fb9e901
parent0fb6cc4dde6e44907cd85f9c33e09f78592a9c12 (diff)
qcacld-3.0: Add input validation for SENDACTIONFRAME
This is a qcacld-2.0 to qcacld-3.0 propagation. Add input validation for SENDACTIONFRAME driver command. Change-Id: I3d1bf424e5e0f9a3b6f4662dd12a3a7314c7eace CRs-Fixed: 1001449
-rw-r--r--core/hdd/src/wlan_hdd_ioctl.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c
index 775ec138633e..5fdab298fb8c 100644
--- a/core/hdd/src/wlan_hdd_ioctl.c
+++ b/core/hdd/src/wlan_hdd_ioctl.c
@@ -1071,16 +1071,15 @@ static int hdd_parse_reassoc(hdd_adapter_t *adapter, const char *command)
static int
hdd_sendactionframe(hdd_adapter_t *adapter, const uint8_t *bssid,
const uint8_t channel, const uint8_t dwell_time,
- const uint8_t payload_len, const uint8_t *payload)
+ const int payload_len, const uint8_t *payload)
{
struct ieee80211_channel chan;
- uint8_t frame_len;
+ int frame_len, ret = 0;
uint8_t *frame;
struct ieee80211_hdr_3addr *hdr;
u64 cookie;
hdd_station_ctx_t *pHddStaCtx;
hdd_context_t *hdd_ctx;
- int ret = 0;
tpSirMacVendorSpecificFrameHdr pVendorSpecific =
(tpSirMacVendorSpecificFrameHdr) payload;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
@@ -1259,29 +1258,42 @@ hdd_parse_sendactionframe_v1(hdd_adapter_t *adapter, const char *command)
* Return: 0 for success non-zero for failure
*/
static int
-hdd_parse_sendactionframe_v2(hdd_adapter_t *adapter, const char *command)
+hdd_parse_sendactionframe_v2(hdd_adapter_t *adapter,
+ const char *command, int total_len)
{
struct android_wifi_af_params *params;
tSirMacAddr bssid;
int ret;
- /* params are large so keep off the stack */
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params)
- return -ENOMEM;
-
/* The params are located after "SENDACTIONFRAME " */
- memcpy(params, command + 16, sizeof(*params));
+ total_len -= 16;
+ params = (struct android_wifi_af_params *)(command + 16);
+
+ if (params->len <= 0 || params->len > ANDROID_WIFI_ACTION_FRAME_SIZE ||
+ (params->len > total_len)) {
+ hdd_err("Invalid payload length: %d", params->len);
+ return -EINVAL;
+ }
- if (!mac_pton(params->bssid, (u8 *) &bssid)) {
+ if (!mac_pton(params->bssid, (u8 *)&bssid)) {
hdd_err("MAC address parsing failed");
- ret = -EINVAL;
- } else {
- ret = hdd_sendactionframe(adapter, bssid, params->channel,
- params->dwell_time, params->len,
- params->data);
+ return -EINVAL;
+ }
+
+ if (params->channel < 0 ||
+ params->channel > WNI_CFG_CURRENT_CHANNEL_STAMAX) {
+ hdd_err("Invalid channel: %d", params->channel);
+ return -EINVAL;
+ }
+
+ if (params->dwell_time < 0) {
+ hdd_err("Invalid dwell_time: %d", params->dwell_time);
+ return -EINVAL;
}
- kfree(params);
+
+ ret = hdd_sendactionframe(adapter, bssid, params->channel,
+ params->dwell_time, params->len, params->data);
+
return ret;
}
@@ -1300,7 +1312,8 @@ hdd_parse_sendactionframe_v2(hdd_adapter_t *adapter, const char *command)
* Return: 0 for success non-zero for failure
*/
static int
-hdd_parse_sendactionframe(hdd_adapter_t *adapter, const char *command)
+hdd_parse_sendactionframe(hdd_adapter_t *adapter, const char *command,
+ int total_len)
{
int ret;
@@ -1317,11 +1330,18 @@ hdd_parse_sendactionframe(hdd_adapter_t *adapter, const char *command)
* SENDACTIONFRAME xx:xx:xx:xx:xx:xx*
* 111111111122222222223333
* 0123456789012345678901234567890123
+ * For both the commands, a valid command must have atleast
+ * first 34 length of data.
*/
+ if (total_len < 34) {
+ hdd_err("Invalid command (total_len=%d)", total_len);
+ return -EINVAL;
+ }
+
if (command[33]) {
ret = hdd_parse_sendactionframe_v1(adapter, command);
} else {
- ret = hdd_parse_sendactionframe_v2(adapter, command);
+ ret = hdd_parse_sendactionframe_v2(adapter, command, total_len);
}
return ret;
@@ -3708,7 +3728,8 @@ static int drv_cmd_send_action_frame(hdd_adapter_t *adapter,
uint8_t command_len,
hdd_priv_data_t *priv_data)
{
- return hdd_parse_sendactionframe(adapter, command);
+ return hdd_parse_sendactionframe(adapter, command,
+ priv_data->total_len);
}
static int drv_cmd_get_roam_scan_channel_min_time(hdd_adapter_t *adapter,