summaryrefslogtreecommitdiff
path: root/umac
diff options
context:
space:
mode:
authorgaurank kathpalia <gkathpal@codeaurora.org>2018-02-07 19:56:00 +0530
committersnandini <snandini@codeaurora.org>2018-02-13 05:47:44 -0800
commit7d65c1b32df795d4e95cdf2cfb624126f5125220 (patch)
tree928a1b63e3c904f007fae7e3a7007dc458c10de5 /umac
parent40789ff92d544960bd6922cf70d2fed1949ea4a7 (diff)
downloadqca-wfi-host-cmn-7d65c1b32df795d4e95cdf2cfb624126f5125220.tar.gz
qcacmn: Add individual length checks to Beacon Information element
Currently there is no individual length check to each IE, which could probably result in buffer overead. Minimum length should be checked for each varibale IE for avoid the same. Also some fixed IEs should have a length check of not greater than the size of their respective structures to avoid corrupting other IE data. Fix is to add a length check to each individual IE to avoid corrupting other IEs and also to prevent reception of any IE of invalid length IE. Change-Id: I9a0914861d7ff2871ac72ad7357ebbb7ef10eeb3 CRs-Fixed: 2183014
Diffstat (limited to 'umac')
-rw-r--r--umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h38
-rw-r--r--umac/scan/dispatcher/src/wlan_scan_utils_api.c115
2 files changed, 140 insertions, 13 deletions
diff --git a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h
index a196ac51f..9fa2fd683 100644
--- a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h
+++ b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h
@@ -86,6 +86,27 @@
#define WLAN_MAX_IE_LEN 255
#define WLAN_RSN_IE_LEN 22
+/* Individual element IEs length checks */
+
+#define WLAN_SUPPORTED_RATES_IE_MAX_LEN 8
+#define WLAN_DS_PARAM_IE_MAX_LEN 1
+#define WLAN_COUNTRY_IE_MIN_LEN 3
+#define WLAN_QUIET_IE_MAX_LEN 6
+#define WLAN_CSA_IE_MAX_LEN 3
+#define WLAN_XCSA_IE_MAX_LEN 4
+#define WLAN_SECCHANOFF_IE_MAX_LEN 1
+#define WLAN_EXT_SUPPORTED_RATES_IE_MAX_LEN 12
+#define WLAN_EXTCAP_IE_MAX_LEN 15
+#define WLAN_FILS_INDICATION_IE_MIN_LEN 2
+#define WLAN_MOBILITY_DOMAIN_IE_MAX_LEN 3
+#define WLAN_OPMODE_IE_MAX_LEN 1
+#define WLAN_IBSSDFS_IE_MIN_LEN 7
+#define WLAN_EXT_ESP_IE_MAX_LEN 96
+#define WLAN_HE_CAP_IE_MIN_LEN 18
+#define WLAN_HE_CAP_IE_MAX_LEN 53
+#define WLAN_HE_OP_IE_MIN_LEN 6
+#define WLAN_HE_OP_IE_MAX_LEN 10
+
/* HT capability flags */
#define WLAN_HTCAP_C_ADVCODING 0x0001
#define WLAN_HTCAP_C_CHWIDTH40 0x0002
@@ -414,6 +435,8 @@ struct wlan_rsn_ie_hdr {
u8 version[2];
};
+#define WLAN_RSN_IE_MIN_LEN 3
+
/**
* struct wlan_rsn_ie: rsn ie info
* @ver: RSN ver
@@ -440,6 +463,8 @@ struct wlan_rsn_ie {
uint32_t mgmt_cipher_suite;
};
+#define WLAN_WAPI_IE_MIN_LEN 20
+
/**
* struct wlan_wpa_ie_hdr: wpa ie header
* @elem_id: Wpa element id, vender specific.
@@ -683,9 +708,11 @@ struct fils_indication_ie {
uint16_t is_fils_sk_auth_pfs_supported:1;
uint16_t is_pk_auth_supported:1;
uint16_t reserved:4;
- uint8_t variable_data[255];
+ uint8_t variable_data[253];
} qdf_packed;
+#define WLAN_VENDOR_HT_IE_OFFSET_LEN 4
+
/**
* struct wlan_vendor_ie_htcap: vendor private HT Capability IE
* @id: HT IE
@@ -776,6 +803,9 @@ struct wlan_vendor_ie_htinfo {
struct wlan_ie_htinfo_cmn hi_ie;
} qdf_packed;
+#define WLAN_VENDOR_VHTCAP_IE_OFFSET 7
+#define WLAN_VENDOR_VHTOP_IE_OFFSET 21
+
/**
* struct wlan_ie_vhtcaps - VHT capabilities
* @elem_id: VHT caps IE
@@ -869,12 +899,14 @@ struct wlan_country_ie {
* struct wlan_country_ie: country IE
* @ie: QBSS IE
* @len: IE len
+ * @station_count: number of station associated
* @qbss_chan_load: qbss channel load
* @qbss_load_avail: qbss_load_avail
*/
struct qbss_load_ie {
uint8_t ie;
uint8_t len;
+ uint16_t station_count;
uint8_t qbss_chan_load;
uint16_t qbss_load_avail;
} qdf_packed;
@@ -893,6 +925,8 @@ struct wlan_bcn_frame {
struct ie_header ie;
} qdf_packed;
+#define WLAN_TIM_IE_MIN_LENGTH 4
+
/**
* struct wlan_tim_ie: tim IE
* @tim_ie: Time IE
@@ -908,7 +942,7 @@ struct wlan_tim_ie {
uint8_t tim_count; /* DTIM count */
uint8_t tim_period; /* DTIM period */
uint8_t tim_bitctl; /* bitmap control */
- uint8_t tim_bitmap[1]; /* variable-length bitmap */
+ uint8_t tim_bitmap[251]; /* variable-length bitmap */
} qdf_packed;
/**
diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c
index 4eb39ea7d..fa8ecfafd 100644
--- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c
+++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c
@@ -341,7 +341,7 @@ util_scan_is_hidden_ssid(struct ie_ssid *ssid)
return true;
}
-static void
+static QDF_STATUS
util_scan_parse_extn_ie(struct scan_cache_entry *scan_params,
struct ie_header *ie)
{
@@ -352,24 +352,32 @@ util_scan_parse_extn_ie(struct scan_cache_entry *scan_params,
scan_params->ie_list.srp = (uint8_t *)ie;
break;
case WLAN_EXTN_ELEMID_HECAP:
+ if ((extn_ie->ie_len < WLAN_HE_CAP_IE_MIN_LEN) ||
+ (extn_ie->ie_len > WLAN_HE_CAP_IE_MAX_LEN))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.hecap = (uint8_t *)ie;
break;
case WLAN_EXTN_ELEMID_HEOP:
+ if ((extn_ie->ie_len < WLAN_HE_OP_IE_MIN_LEN) ||
+ (extn_ie->ie_len > WLAN_HE_OP_IE_MAX_LEN))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.heop = (uint8_t *)ie;
break;
case WLAN_EXTN_ELEMID_ESP:
+ if (extn_ie->ie_len > WLAN_EXT_ESP_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.esp = (uint8_t *)ie;
break;
default:
break;
}
+ return QDF_STATUS_SUCCESS;
}
-static void
+static QDF_STATUS
util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params,
struct ie_header *ie)
{
-
if (scan_params->ie_list.vendor == NULL)
scan_params->ie_list.vendor = (uint8_t *)ie;
@@ -397,20 +405,51 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params,
scan_params->ie_list.sonadv = (uint8_t *)ie;
} else if (is_ht_cap((uint8_t *)ie)) {
/* we only care if there isn't already an HT IE (ANA) */
- if (scan_params->ie_list.htcap == NULL)
+ if (scan_params->ie_list.htcap == NULL) {
+ if (ie->ie_len != (WLAN_VENDOR_HT_IE_OFFSET_LEN +
+ sizeof(struct htcap_cmn_ie)))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.htcap =
- (uint8_t *)&(((struct wlan_vendor_ie_htcap *)ie)->ie);
+ (uint8_t *)&(((struct wlan_vendor_ie_htcap *)ie)->ie);
+ }
} else if (is_ht_info((uint8_t *)ie)) {
/* we only care if there isn't already an HT IE (ANA) */
- if (scan_params->ie_list.htinfo == NULL)
+ if (scan_params->ie_list.htinfo == NULL) {
+ if (ie->ie_len != WLAN_VENDOR_HT_IE_OFFSET_LEN +
+ sizeof(struct wlan_ie_htinfo_cmn))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.htinfo =
(uint8_t *)&(((struct wlan_vendor_ie_htinfo *)
ie)->hi_ie);
+ }
} else if (is_interop_vht((uint8_t *)ie) &&
!(scan_params->ie_list.vhtop)) {
+ uint8_t *vendor_ie = (uint8_t *)(ie);
+
+ if (ie->ie_len < ((WLAN_VENDOR_VHTCAP_IE_OFFSET +
+ sizeof(struct wlan_ie_vhtcaps)) -
+ sizeof(struct ie_header)))
+ return QDF_STATUS_E_INVAL;
+ vendor_ie = ((uint8_t *)(ie)) + WLAN_VENDOR_VHTCAP_IE_OFFSET;
+ if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtcaps)) -
+ sizeof(struct ie_header))
+ return QDF_STATUS_E_INVAL;
/* location where Interop Vht Cap IE and VHT OP IE Present */
- scan_params->ie_list.vhtcap = (((uint8_t *)(ie)) + 7);
- scan_params->ie_list.vhtop = (((uint8_t *)(ie)) + 21);
+ scan_params->ie_list.vhtcap = (((uint8_t *)(ie)) +
+ WLAN_VENDOR_VHTCAP_IE_OFFSET);
+ if (ie->ie_len > ((WLAN_VENDOR_VHTCAP_IE_OFFSET +
+ sizeof(struct wlan_ie_vhtcaps)) -
+ sizeof(struct ie_header)) &&
+ ie->ie_len < ((WLAN_VENDOR_VHTOP_IE_OFFSET +
+ sizeof(struct wlan_ie_vhtop)) -
+ sizeof(struct ie_header)))
+ return QDF_STATUS_E_INVAL;
+ vendor_ie = ((uint8_t *)(ie)) + WLAN_VENDOR_VHTOP_IE_OFFSET;
+ if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtop) -
+ sizeof(struct ie_header)))
+ return QDF_STATUS_E_INVAL;
+ scan_params->ie_list.vhtop = (((uint8_t *)(ie)) +
+ WLAN_VENDOR_VHTOP_IE_OFFSET);
} else if (is_bwnss_oui((uint8_t *)ie)) {
/*
* Bandwidth-NSS map has sub-type & version.
@@ -420,6 +459,7 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params,
} else if (is_mbo_oce_oui((uint8_t *)ie)) {
scan_params->ie_list.mbo_oce = (uint8_t *)ie;
}
+ return QDF_STATUS_SUCCESS;
}
static QDF_STATUS
@@ -449,56 +489,89 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params)
switch (ie->ie_id) {
case WLAN_ELEMID_SSID:
+ if (ie->ie_len > (sizeof(struct ie_ssid) -
+ sizeof(struct ie_header)))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.ssid = (uint8_t *)ie;
break;
case WLAN_ELEMID_RATES:
+ if (ie->ie_len > WLAN_SUPPORTED_RATES_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.rates = (uint8_t *)ie;
break;
case WLAN_ELEMID_DSPARMS:
+ if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.ds_param = (uint8_t *)ie;
scan_params->channel.chan_idx =
((struct ds_ie *)ie)->cur_chan;
break;
case WLAN_ELEMID_TIM:
+ if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.tim = (uint8_t *)ie;
scan_params->dtim_period =
((struct wlan_tim_ie *)ie)->tim_period;
break;
case WLAN_ELEMID_COUNTRY:
+ if (ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.country = (uint8_t *)ie;
break;
case WLAN_ELEMID_QBSS_LOAD:
+ if (ie->ie_len != sizeof(struct qbss_load_ie) -
+ sizeof(struct ie_header))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.qbssload = (uint8_t *)ie;
break;
case WLAN_ELEMID_CHANSWITCHANN:
+ if (ie->ie_len != WLAN_CSA_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.csa = (uint8_t *)ie;
break;
case WLAN_ELEMID_IBSSDFS:
+ if (ie->ie_len < WLAN_IBSSDFS_IE_MIN_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.ibssdfs = (uint8_t *)ie;
break;
case WLAN_ELEMID_QUIET:
+ if (ie->ie_len != WLAN_QUIET_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.quiet = (uint8_t *)ie;
break;
case WLAN_ELEMID_ERP:
+ if (ie->ie_len != (sizeof(struct erp_ie) -
+ sizeof(struct ie_header)))
+ return QDF_STATUS_E_INVAL;
scan_params->erp = ((struct erp_ie *)ie)->value;
break;
case WLAN_ELEMID_HTCAP_ANA:
+ if (ie->ie_len != sizeof(struct htcap_cmn_ie))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.htcap =
(uint8_t *)&(((struct htcap_ie *)ie)->ie);
break;
case WLAN_ELEMID_RSN:
+ if (ie->ie_len < WLAN_RSN_IE_MIN_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.rsn = (uint8_t *)ie;
break;
case WLAN_ELEMID_XRATES:
scan_params->ie_list.xrates = (uint8_t *)ie;
break;
case WLAN_ELEMID_EXTCHANSWITCHANN:
+ if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.xcsa = (uint8_t *)ie;
break;
case WLAN_ELEMID_SECCHANOFFSET:
+ if (ie->ie_len != WLAN_SECCHANOFF_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.secchanoff = (uint8_t *)ie;
break;
case WLAN_ELEMID_HTINFO_ANA:
+ if (ie->ie_len != sizeof(struct wlan_ie_htinfo_cmn))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.htinfo =
(uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie);
scan_params->channel.chan_idx =
@@ -506,26 +579,42 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params)
(scan_params->ie_list.htinfo))->hi_ctrlchannel;
break;
case WLAN_ELEMID_WAPI:
+ if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.wapi = (uint8_t *)ie;
break;
case WLAN_ELEMID_XCAPS:
+ if (ie->ie_len > WLAN_EXTCAP_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.extcaps = (uint8_t *)ie;
break;
case WLAN_ELEMID_VHTCAP:
+ if (ie->ie_len != (sizeof(struct wlan_ie_vhtcaps) -
+ sizeof(struct ie_header)))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.vhtcap = (uint8_t *)ie;
break;
case WLAN_ELEMID_VHTOP:
+ if (ie->ie_len != (sizeof(struct wlan_ie_vhtop) -
+ sizeof(struct ie_header)))
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.vhtop = (uint8_t *)ie;
break;
case WLAN_ELEMID_OP_MODE_NOTIFY:
+ if (ie->ie_len != WLAN_OPMODE_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.opmode = (uint8_t *)ie;
break;
case WLAN_ELEMID_MOBILITY_DOMAIN:
+ if (ie->ie_len != WLAN_MOBILITY_DOMAIN_IE_MAX_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.mdie = (uint8_t *)ie;
break;
case WLAN_ELEMID_VENDOR:
- util_scan_parse_vendor_ie(scan_params,
- ie);
+ status = util_scan_parse_vendor_ie(scan_params,
+ ie);
+ if (QDF_IS_STATUS_ERROR(status))
+ return status;
break;
case WLAN_ELEMID_CHAN_SWITCH_WRAP:
scan_params->ie_list.cswrp = (uint8_t *)ie;
@@ -542,10 +631,14 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params)
}
break;
case WLAN_ELEMID_FILS_INDICATION:
+ if (ie->ie_len < WLAN_FILS_INDICATION_IE_MIN_LEN)
+ return QDF_STATUS_E_INVAL;
scan_params->ie_list.fils_indication = (uint8_t *)ie;
break;
case WLAN_ELEMID_EXTN_ELEM:
- util_scan_parse_extn_ie(scan_params, ie);
+ status = util_scan_parse_extn_ie(scan_params, ie);
+ if (QDF_IS_STATUS_ERROR(status))
+ return status;
break;
default:
break;