Преглед изворни кода

qcacld-3.0: Invalid pmkid in the FT-EAP disconnection case

During FT-EAP roaming after session timeout if the FTIE received
in the EAPOL of full EAP is improper, the supplicant would
disconnect the AP with the reason FTIE mismatch.
During this disconnection supplicant flushes all the existing PMK
cache entries and eventually the framework would add these cache
entries again (apparently, the current entry would be with the
older PMK). On this addition to the driver, there is no connected
profile and thus no MDID is associated to this PMKSA entry(AP1-PMK1).
Further, on the fresh (Full EAP) connection to the AP2 with the
same MDID, a new cache entry gets added and thus MDID from the
connected profile gets associated with the PMKSA cache entry. At
this point of time, there are two PMKSA cache entries (AP1-PMK1
without MDID and AP2-PMK2 with MDID).
Adding further, if the incorrect PMK (without MDID / stale entry)
i.e. PMK1 is given to the firmware on the RSO command for the
specific BSSID (here AP1) during roam, further roams shall be
calculated with this PMK1 and result in to the invalid pmkid
issue.
Thus, avoid this situation by removing that stale PMKSA entry in
the driver and this entry can be deleted only when it is associated
with the MDID. Driver on the new pmksa addition shall check for the
matching pmksa cache entry with the MDID and delete the earlier ones.
To associate the MDID, this commit checks for the same from the scan
entry of the BSSID, if there is no connected profile for the same
(this happened when the framework has added the cache entry when in
the disconnected state).

Change-Id: If81d66059173dda8d7a2940ca10dc96ef16e125c
CRs-Fixed: 2972115
Srikanth Marepalli пре 3 година
родитељ
комит
0ec902c074

+ 7 - 6
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -3953,11 +3953,12 @@ void cm_update_pmk_cache_ft(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
 	}
 
 	/*
-	 * In FT connection fetch the MDID from Session and send it to crypto
-	 * so that it will update the crypto PMKSA table with the MDID for the
-	 * matching BSSID or SSID PMKSA entry. And delete the old/stale PMK
-	 * cache entries for the same mobility domain as of the newly added
-	 * entry to avoid multiple PMK cache entries for the same MDID.
+	 * In FT connection fetch the MDID from Session or scan result whichever
+	 * and send it to crypto so that it will update the crypto PMKSA table
+	 * with the MDID for the matching BSSID or SSID PMKSA entry. And delete
+	 * the old/stale PMK cache entries for the same mobility domain as of
+	 * the newly added entry to avoid multiple PMK cache entries for the
+	 * same MDID.
 	 */
 	wlan_vdev_get_bss_peer_mac(vdev, &pmksa.bssid);
 	wlan_vdev_mlme_get_ssid(vdev, pmksa.ssid, &pmksa.ssid_len);
@@ -3968,7 +3969,7 @@ void cm_update_pmk_cache_ft(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
 	if (src_cfg.bool_value) {
 		pmksa.mdid.mdie_present = 1;
 		pmksa.mdid.mobility_domain = src_cfg.uint_value;
-		mlme_debug("copied the MDID from session to PMKSA");
+		mlme_debug("copied the MDID to PMKSA");
 
 		status = wlan_crypto_update_pmk_cache_ft(vdev, &pmksa);
 		if (status == QDF_STATUS_SUCCESS)

+ 3 - 1
core/hdd/src/wlan_hdd_cfg80211.c

@@ -19699,10 +19699,12 @@ static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
 		qdf_mem_free(pmksa);
 	}
 
-	if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len)
+	if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len) {
 		sme_roam_set_psk_pmk(mac_handle, adapter->vdev_id,
 				     pmk_cache->pmk, pmk_cache->pmk_len,
 				     false);
+		sme_set_pmk_cache_ft(mac_handle, adapter->vdev_id, pmk_cache);
+	}
 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
 
 	return result;

+ 19 - 0
core/sme/inc/sme_api.h

@@ -597,6 +597,18 @@ void sme_get_pmk_info(mac_handle_t mac_handle, uint8_t session_id,
 QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId,
 				uint8_t *psk_pmk, size_t pmk_len,
 				bool update_to_fw);
+
+/**
+ * sme_set_pmk_cache_ft() - a wrapper function to request CSR to save MDID
+ * This is a synchronous call.
+ * @mac_handle:  Global structure
+ * @session_id:   SME session id
+ * @pmk_cache:    pointer to pmk cache structure wlan_crypto_pmksa
+ *
+ * Return: QDF_STATUS -status whether MDID is set or not
+ */
+QDF_STATUS sme_set_pmk_cache_ft(mac_handle_t mac_handle, uint8_t session_id,
+				struct wlan_crypto_pmksa *pmk_cache);
 #else
 static inline
 void sme_get_pmk_info(mac_handle_t mac_handle, uint8_t session_id,
@@ -624,6 +636,13 @@ QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline
+QDF_STATUS sme_set_pmk_cache_ft(mac_handle_t mac_handle, uint8_t session_id,
+				struct wlan_crypto_pmksa *pmk_cache)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 QDF_STATUS sme_get_config_param(mac_handle_t mac_handle,

+ 14 - 0
core/sme/src/common/sme_api.c

@@ -3465,6 +3465,20 @@ QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId,
 	}
 	return status;
 }
+
+QDF_STATUS sme_set_pmk_cache_ft(mac_handle_t mac_handle, uint8_t session_id,
+				struct wlan_crypto_pmksa *pmk_cache)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	struct mac_context *mac = MAC_CONTEXT(mac_handle);
+
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		status = csr_set_pmk_cache_ft(mac, session_id, pmk_cache);
+		sme_release_global_lock(&mac->sme);
+	}
+	return status;
+}
 #endif
 
 /*

+ 43 - 9
core/sme/src/csr/csr_api_roam.c

@@ -5665,19 +5665,34 @@ QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint8_t vdev_id,
 				uint8_t *psk_pmk, size_t pmk_len,
 				bool update_to_fw)
 {
-	int32_t akm;
+	wlan_cm_set_psk_pmk(mac->pdev, vdev_id, psk_pmk, pmk_len);
+	if (update_to_fw)
+		wlan_roam_update_cfg(mac->psoc, vdev_id,
+				     REASON_ROAM_PSK_PMK_CHANGED);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS csr_set_pmk_cache_ft(struct mac_context *mac, uint32_t session_id,
+				struct wlan_crypto_pmksa *pmk_cache)
+{
 	struct wlan_objmgr_vdev *vdev;
+	int32_t akm;
+
+	if (!CSR_IS_SESSION_VALID(mac, session_id)) {
+		sme_err("session %d not found", session_id);
+		return QDF_STATUS_E_INVAL;
+	}
 
-	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, session_id,
 						    WLAN_LEGACY_SME_ID);
 	if (!vdev) {
 		sme_err("vdev is NULL");
 		return QDF_STATUS_E_FAILURE;
 	}
-	wlan_cm_set_psk_pmk(mac->pdev, vdev_id, psk_pmk, pmk_len);
+
 	akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
-
 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM)) {
 		sme_debug("PMK update is not required for ESE");
 		return QDF_STATUS_SUCCESS;
@@ -5688,13 +5703,32 @@ QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint8_t vdev_id,
 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384) ||
 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) {
 		sme_debug("Auth type: %x update the MDID in cache", akm);
-		cm_update_pmk_cache_ft(mac->psoc, vdev_id);
-	}
+		cm_update_pmk_cache_ft(mac->psoc, session_id);
+	} else {
+		struct cm_roam_values_copy src_cfg;
+		QDF_STATUS status = QDF_STATUS_E_FAILURE;
+		tCsrScanResultInfo *scan_res;
 
-	if (update_to_fw)
-		wlan_roam_update_cfg(mac->psoc, vdev_id,
-				     REASON_ROAM_PSK_PMK_CHANGED);
+		scan_res = qdf_mem_malloc(sizeof(tCsrScanResultInfo));
+		if (!scan_res)
+			return QDF_STATUS_E_NOMEM;
 
+		status = csr_scan_get_result_for_bssid(mac, &pmk_cache->bssid,
+						       scan_res);
+		if (QDF_IS_STATUS_SUCCESS(status) &&
+		    scan_res->BssDescriptor.mdiePresent) {
+			sme_debug("Update MDID in cache from scan_res");
+			src_cfg.bool_value = true;
+			src_cfg.uint_value =
+				(scan_res->BssDescriptor.mdie[0] |
+				 (scan_res->BssDescriptor.mdie[1] << 8));
+			wlan_cm_roam_cfg_set_value(mac->psoc, session_id,
+						   MOBILITY_DOMAIN, &src_cfg);
+			cm_update_pmk_cache_ft(mac->psoc, session_id);
+		}
+		qdf_mem_free(scan_res);
+		scan_res = NULL;
+	}
 	return QDF_STATUS_SUCCESS;
 }
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */

+ 12 - 0
core/sme/src/csr/csr_inside_api.h

@@ -396,6 +396,18 @@ void csr_get_pmk_info(struct mac_context *mac_ctx, uint8_t session_id,
 QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint8_t vdev_id,
 				uint8_t *psk_pmk, size_t pmk_len,
 				bool update_to_fw);
+
+/**
+ * csr_set_pmk_cache_ft() - store MDID in PMK cache
+ *
+ * @mac  - pointer to global structure for MAC
+ * @session_id - Sme session id
+ * @pmk_cache: pointer to a structure of PMK
+ *
+ * Return QDF_STATUS - usually it succeed unless session_id is not found
+ */
+QDF_STATUS csr_set_pmk_cache_ft(struct mac_context *mac, uint32_t session_id,
+				struct wlan_crypto_pmksa *pmk_cache);
 #endif
 
 /*