Browse Source

qcacld-3.0: Possible OOB access in wlan_hdd_cfg80211_start_bss()

In wlan_hdd_cfg80211_start_bss(), beacon head buffer is typecast
to ieee80211_mgmt structure without checking for buffer length
against beacon header length which may cause OOB access
while accessing iee80211_mgmt structure.

To address this, add check for beacon head length against beacon
header length before typecasting to iee80211_mgmt structure.

Also while accessing supported rates, length given to function
wlan_hdd_cfg80211_get_ie_ptr() is the total length of management
frame that also includes header length which may cause OOB access
while getting supported rates.

To address this, send only beacon data length and exclude header
length to function wlan_hdd_cfg80211_get_ie_ptr().

Change-Id: I442b236e48c3be8cbd8019c5c339593f9aa74e3e
CRs-Fixed: 2335957
Dundi Raviteja 6 years ago
parent
commit
5296f49644
1 changed files with 23 additions and 1 deletions
  1. 23 1
      core/hdd/src/wlan_hdd_hostapd.c

+ 23 - 1
core/hdd/src/wlan_hdd_hostapd.c

@@ -4575,6 +4575,7 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 	tsap_config_t *pConfig;
 	struct hdd_beacon_data *pBeacon = NULL;
 	struct ieee80211_mgmt *pMgmt_frame;
+	struct ieee80211_mgmt mgmt;
 	const uint8_t *pIe = NULL;
 	uint16_t capab_info;
 	eCsrAuthType RSNAuthType;
@@ -4596,6 +4597,7 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 	enum dfs_mode mode;
 	struct hdd_adapter *sta_adapter;
 	uint8_t ignore_cac = 0;
+	uint8_t beacon_fixed_len;
 	int value;
 	bool val;
 	uint32_t auto_channel_select_weight =
@@ -4699,6 +4701,22 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 	}
 
 	pBeacon = adapter->session.ap.beacon;
+
+	/*
+	 * beacon_fixed_len is the fixed length of beacon
+	 * frame which includes only mac header length and
+	 * beacon manadatory fields like timestamp,
+	 * beacon_int and capab_info.
+	 * (From the reference of struct ieee80211_mgmt)
+	 */
+	beacon_fixed_len = sizeof(mgmt) - sizeof(mgmt.u) +
+			   sizeof(mgmt.u.beacon);
+	if (pBeacon->head_len < beacon_fixed_len) {
+		hdd_err("Invalid beacon head len");
+		ret = -EINVAL;
+		goto error;
+	}
+
 	pMgmt_frame = (struct ieee80211_mgmt *)pBeacon->head;
 
 	pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
@@ -5016,9 +5034,13 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 
 	if (!(ssid && qdf_str_len(PRE_CAC_SSID) == ssid_len &&
 	      (0 == qdf_mem_cmp(ssid, PRE_CAC_SSID, ssid_len)))) {
+		uint16_t beacon_data_len;
+
+		beacon_data_len = pBeacon->head_len - beacon_fixed_len;
+
 		pIe = wlan_get_ie_ptr_from_eid(WLAN_EID_SUPP_RATES,
 					&pMgmt_frame->u.beacon.variable[0],
-					pBeacon->head_len);
+					beacon_data_len);
 
 		if (pIe != NULL) {
 			pIe++;