TDLS : Protect the Adapter access with a mutex.
The adapter accesses by the TDLS code is not protected with the
concurrent access of the same by the cfg80211 callbacks (add / del
interface, change interface) and thus results in a kernel panic.This
commit provides the concurrent access to the adapter through a mutex.
Change-Id: I1bb9845097b40ba7d622950a119e934731c822b9
CRs-fixed: 546843
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 9787000..3abd444 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -2710,13 +2710,28 @@
hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
}
}
+#ifdef FEATURE_WLAN_TDLS
+ /* A Mutex Lock is introduced while changing the mode to
+ * protect the concurrent access for the Adapters by TDLS
+ * module.
+ */
+ if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: unable to lock list", __func__);
+ return -EINVAL;
+ }
+#endif
//De-init the adapter.
hdd_stop_adapter( pHddCtx, pAdapter );
hdd_deinit_adapter( pHddCtx, pAdapter );
memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
+#ifdef FEATURE_WLAN_TDLS
+ mutex_unlock(&pHddCtx->tdls_lock);
+#endif
//Disable BMPS and IMPS if enabled
//before starting Go
@@ -2793,6 +2808,19 @@
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_ADHOC:
+#ifdef FEATURE_WLAN_TDLS
+
+ /* A Mutex Lock is introduced while changing the mode to
+ * protect the concurrent access for the Adapters by TDLS
+ * module.
+ */
+ if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: unable to lock list", __func__);
+ return -EINVAL;
+ }
+#endif
hdd_stop_adapter( pHddCtx, pAdapter );
hdd_deinit_adapter( pHddCtx, pAdapter );
wdev->iftype = type;
@@ -2812,6 +2840,9 @@
memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
hdd_set_station_ops( pAdapter->dev );
status = hdd_init_station_mode( pAdapter );
+#ifdef FEATURE_WLAN_TDLS
+ mutex_unlock(&pHddCtx->tdls_lock);
+#endif
if( VOS_STATUS_SUCCESS != status )
return -EOPNOTSUPP;
/* In case of JB, for P2P-GO, only change interface will be called,
@@ -2931,7 +2962,7 @@
return -EBUSY;
}
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
if ( NULL == pTdlsPeer ) {
VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
@@ -2965,7 +2996,7 @@
}
/* when others are on-going, we want to change link_status to idle */
- if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
+ if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE))
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: " MAC_ADDRESS_STR
@@ -2988,7 +3019,7 @@
else
{
hddTdlsPeer_t *pTdlsPeer;
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
@@ -7881,7 +7912,7 @@
if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
{
- if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE))
+ if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE))
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"%s: " MAC_ADDRESS_STR
@@ -7925,7 +7956,7 @@
else
{
hddTdlsPeer_t *pTdlsPeer;
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
{
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
@@ -7950,7 +7981,7 @@
{
hddTdlsPeer_t *pTdlsPeer;
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac, TRUE);
if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
responder = pTdlsPeer->is_responder;
@@ -8078,7 +8109,7 @@
return status;
}
- pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer);
+ pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
if ( NULL == pTdlsPeer ) {
hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR " (oper %d) not exsting. ignored",