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
This commit is contained in:
Padma, Santhosh Kumar 2018-06-21 17:48:48 +05:30 • committed by nshrivas
commit dbef1c57f4

View file

@ -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