summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Johnson <jjohnson@codeaurora.org>2016-11-09 09:01:10 -0800
committerqcabuildsw <qcabuildsw@localhost>2016-12-14 14:06:53 -0800
commitfa484bbf8ae64daebedb487dad56b46b22bb32b8 (patch)
treeefac022e2c7db3476c65bdca3e88c0030dddbbaa
parent083407455f68671074223d55145a873c93e7426d (diff)
downloadqcacld-fa484bbf8ae64daebedb487dad56b46b22bb32b8.tar.gz
qcacld-3.0: Properly parse PNO vendor command
This is a qcacld-2.0 to qcacld-3.0 propagation. Currently there is a single wlan_hdd_extscan_config_policy which contains entries for both EXTSCAN and PNO attributes. However the EXTSCAN and PNO attributes have separate and overlapping assignments. Therefore one policy cannot be used by both types of commands. In addition, when parsing nested PNO attributes the policy is not used, and hence no checking is performed on the nested data. This can result in a buffer overflow. To address these issues introduce a new policy for PNO vendor commands, and use that policy both when parsing the initial command and when parsing the nested attributes. Furthermore add a zero length SSID check to prevent underflow. Change-Id: I92c8fc7ca1c44971502ea68b5486a2b3ae941cc5 CRs-Fixed: 1087209
-rw-r--r--core/hdd/src/wlan_hdd_ext_scan.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c
index 581f6e6fd6..349ea8f2e4 100644
--- a/core/hdd/src/wlan_hdd_ext_scan.c
+++ b/core/hdd/src/wlan_hdd_ext_scan.c
@@ -112,15 +112,6 @@ static const struct nla_policy wlan_hdd_extscan_config_policy
.type = NLA_U32},
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = {
.type = NLA_U32},
- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
- .type = NLA_U32 },
- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
- .type = NLA_BINARY,
- .len = IEEE80211_MAX_SSID_LEN },
- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = {
- .type = NLA_U8 },
- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = {
- .type = NLA_U8 },
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = {
.type = NLA_BINARY,
.len = IEEE80211_MAX_SSID_LEN + 1 },
@@ -139,6 +130,23 @@ static const struct nla_policy wlan_hdd_extscan_config_policy
};
static const struct nla_policy
+wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = {
+ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
+ .type = NLA_U32
+ },
+ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
+ .type = NLA_BINARY,
+ .len = IEEE80211_MAX_SSID_LEN + 1
+ },
+ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = {
+ .type = NLA_U8
+ },
+ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = {
+ .type = NLA_U8
+ },
+};
+
+static const struct nla_policy
wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = {
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = {
.type = NLA_U16},
@@ -3773,19 +3781,18 @@ static int hdd_extscan_epno_fill_network_list(
struct wifi_epno_params *req_msg,
struct nlattr **tb)
{
- struct nlattr *network[
- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
+ struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
struct nlattr *networks;
int rem1, ssid_len;
uint8_t index, *ssid;
index = 0;
nla_for_each_nested(networks,
- tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
- rem1) {
- if (nla_parse(network,
- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
- nla_data(networks), nla_len(networks), NULL)) {
+ tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
+ rem1) {
+ if (nla_parse(network, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
+ nla_data(networks), nla_len(networks),
+ wlan_hdd_pno_config_policy)) {
hdd_err("nla_parse failed");
return -EINVAL;
}
@@ -3798,6 +3805,12 @@ static int hdd_extscan_epno_fill_network_list(
ssid_len = nla_len(
network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
+ /* nla_parse will detect overflow but not underflow */
+ if (0 == ssid_len) {
+ hdd_err("zero ssid length");
+ return -EINVAL;
+ }
+
/* Decrement by 1, don't count null character */
ssid_len--;
@@ -3877,8 +3890,8 @@ static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
}
if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
- data, data_len,
- wlan_hdd_extscan_config_policy)) {
+ data, data_len,
+ wlan_hdd_pno_config_policy)) {
hdd_err("Invalid ATTR");
return -EINVAL;
}