From 7d0e40d328fa092c36b9585516ed29fc6041be55 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Tue, 6 Jun 2017 12:53:28 -0700 Subject: qcacld-3.0: Fix buffer overread & overflow in DISA handler Currently in hdd_fill_encrypt_decrypt_params() there are multiple issues with the incoming cfg80211 vendor command handling: 1) A policy is not supplied when invoking nla_parse() which prevents basic sanity of the incoming attribute stream. 2) The length of attribute QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN is not properly validated. 3) The length of attribute QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA is not properly validated. To address these issues: 1) Create an appropriate nla_policy and specify this policy when invoking nla_parse(). 2) Validate the length of QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN to prevent potential buffer overflow. 3) Validate the length of QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA to prevent potential buffer overread. Change-Id: Ibb86897f249010c94c4098b283aad7a7f95ab9a2 CRs-Fixed: 2054760 --- core/hdd/src/wlan_hdd_disa.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/core/hdd/src/wlan_hdd_disa.c b/core/hdd/src/wlan_hdd_disa.c index c2e99d1..39e6bd1 100644 --- a/core/hdd/src/wlan_hdd_disa.c +++ b/core/hdd/src/wlan_hdd_disa.c @@ -159,6 +159,16 @@ nla_put_failure: return -EINVAL; } +static const struct nla_policy +encrypt_decrypt_policy[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION] = { + .type = NLA_FLAG}, + [QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID] = { + .type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER] = { + .type = NLA_U32}, +}; + /** * hdd_fill_encrypt_decrypt_params () - parses data from user space * and fills encrypt/decrypt parameters @@ -181,7 +191,7 @@ static int hdd_fill_encrypt_decrypt_params(struct encrypt_decrypt_req_params uint8_t fc[2]; if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_MAX, - data, data_len, NULL)) { + data, data_len, encrypt_decrypt_policy)) { hdd_err("Invalid ATTR"); return -EINVAL; } @@ -243,8 +253,8 @@ static int hdd_fill_encrypt_decrypt_params(struct encrypt_decrypt_req_params return -EINVAL; } len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN]); - if (!len) { - hdd_err("Invalid PN length"); + if (!len || len > sizeof(encrypt_decrypt_params->pn)) { + hdd_err("Invalid PN length %u", len); return -EINVAL; } @@ -260,8 +270,8 @@ static int hdd_fill_encrypt_decrypt_params(struct encrypt_decrypt_req_params return -EINVAL; } len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA]); - if (!len) { - hdd_err("Invalid header and payload length"); + if (len < MIN_MAC_HEADER_LEN) { + hdd_err("Invalid header and payload length %u", len); return -EINVAL; } @@ -298,6 +308,10 @@ static int hdd_fill_encrypt_decrypt_params(struct encrypt_decrypt_req_params hdd_notice("mac_hdr_len %d", mac_hdr_len); + if (len < mac_hdr_len) { + hdd_err("Invalid header and payload length %u", len); + return -EINVAL; + } qdf_mem_copy(encrypt_decrypt_params->mac_header, tmp, mac_hdr_len); -- cgit v1.1