From dbef1c57f49fa470df6ef4095aa39086ff817d67 Mon Sep 17 00:00:00 2001 From: "Padma, Santhosh Kumar" Date: Thu, 21 Jun 2018 17:48:48 +0530 Subject: [PATCH] qcacld-3.0: Fix use after free of pCurRoamProfile Currently there is a chance that driver can access pCurRoamProfile even after freeing it. While driver frees pCurRoamProfile as part of csr_roam_process_command in mc thread context/user space context(if there is no active command in sme queue), it can access the same variable as part of __wlan_hdd_cfg80211_set_ext_roam_params in user space context and can result in use after free. Acquire lock before freeing roam profile to fix this issue. Change-Id: I16863f35405fa41424060bb2d12c779681095a85 CRs-Fixed: 2265905 --- core/sme/src/csr/csr_api_roam.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index d3b33c1e4963..b911fcba7367 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -6457,8 +6457,8 @@ tpAniSirGlobal mac_ctx, tSmeCmd *cmd, struct csr_roam_info *roam_info, QDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) { - QDF_STATUS status = QDF_STATUS_SUCCESS; struct csr_roam_info roamInfo; + QDF_STATUS lock_status, status = QDF_STATUS_SUCCESS; uint32_t sessionId = pCommand->sessionId; struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, sessionId); @@ -6475,7 +6475,14 @@ QDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) case eCsrForcedDisassoc: status = csr_roam_process_disassoc_deauth(pMac, pCommand, true, false); + lock_status = sme_acquire_global_lock(&pMac->sme); + if (!QDF_IS_STATUS_SUCCESS(lock_status)) { + csr_roam_complete(pMac, eCsrNothingToJoin, NULL, + sessionId); + return lock_status; + } csr_free_roam_profile(pMac, sessionId); + sme_release_global_lock(&pMac->sme); break; case eCsrSmeIssuedDisassocForHandoff: /* Not to free pMac->roam.pCurRoamProfile (via @@ -6488,12 +6495,26 @@ QDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) case eCsrForcedDisassocMICFailure: status = csr_roam_process_disassoc_deauth(pMac, pCommand, true, true); + lock_status = sme_acquire_global_lock(&pMac->sme); + if (!QDF_IS_STATUS_SUCCESS(lock_status)) { + csr_roam_complete(pMac, eCsrNothingToJoin, NULL, + sessionId); + return lock_status; + } csr_free_roam_profile(pMac, sessionId); + sme_release_global_lock(&pMac->sme); break; case eCsrForcedDeauth: status = csr_roam_process_disassoc_deauth(pMac, pCommand, false, false); + lock_status = sme_acquire_global_lock(&pMac->sme); + if (!QDF_IS_STATUS_SUCCESS(lock_status)) { + csr_roam_complete(pMac, eCsrNothingToJoin, NULL, + sessionId); + return lock_status; + } csr_free_roam_profile(pMac, sessionId); + sme_release_global_lock(&pMac->sme); break; case eCsrHddIssuedReassocToSameAP: case eCsrSmeIssuedReassocToSameAP: @@ -6553,6 +6574,12 @@ QDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) if (pCommand->u.roamCmd.fUpdateCurRoamProfile) { /* Remember the roaming profile */ + lock_status = sme_acquire_global_lock(&pMac->sme); + if (!QDF_IS_STATUS_SUCCESS(lock_status)) { + csr_roam_complete(pMac, eCsrNothingToJoin, NULL, + sessionId); + return lock_status; + } csr_free_roam_profile(pMac, sessionId); pSession->pCurRoamProfile = qdf_mem_malloc(sizeof(struct csr_roam_profile)); @@ -6561,6 +6588,7 @@ QDF_STATUS csr_roam_process_command(tpAniSirGlobal pMac, tSmeCmd *pCommand) pSession->pCurRoamProfile, &pCommand->u.roamCmd.roamProfile); } + sme_release_global_lock(&pMac->sme); } /* * At this point original uapsd_mask is saved in