wlan: Acquire rtnl lock while unregistering SAP ioctls.
As part of ioctl unregister, HOST will set wireless_handlers
to NULL. This may lead to NULL pointer dereference if kernel
is processing any IOCTL simultaneously.
Hence, acquire rtnl_lock while making wireless_handlers to NULL,
as same lock is acquired while processing ioctl.
Change-Id: Ic4f54dd9b8cc1d98b0c4d4cd95e4ee24d7d6f5a4
CRs-Fixed: 788485
diff --git a/CORE/HDD/inc/wlan_hdd_hostapd.h b/CORE/HDD/inc/wlan_hdd_hostapd.h
index af1d26f..0e16923 100644
--- a/CORE/HDD/inc/wlan_hdd_hostapd.h
+++ b/CORE/HDD/inc/wlan_hdd_hostapd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -58,7 +58,7 @@
VOS_STATUS hdd_register_hostapd(hdd_adapter_t *pAdapter, tANI_U8 rtnl_held);
-VOS_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter);
+VOS_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter, tANI_U8 rtnl_held);
eCsrAuthType
hdd_TranslateRSNToCsrAuthType( u_int8_t auth_suite[4]);
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 7e68bf5..5178e98 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1378,7 +1378,7 @@
hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx );
VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter );
hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode );
-void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter );
+void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held );
VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
const v_BOOL_t bCloseSession );
void hdd_set_station_ops( struct net_device *pWlanDev );
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 5a121ba..c67142d 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -7535,7 +7535,7 @@
if (pP2pAdapter)
{
hdd_stop_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
- hdd_deinit_adapter(pHddCtx, pP2pAdapter);
+ hdd_deinit_adapter(pHddCtx, pP2pAdapter, TRUE);
hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
}
}
@@ -7558,7 +7558,7 @@
mutex_lock(&pHddCtx->tdls_lock);
#endif
//De-init the adapter.
- hdd_deinit_adapter( pHddCtx, pAdapter );
+ hdd_deinit_adapter( pHddCtx, pAdapter, TRUE);
memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
@@ -7677,7 +7677,7 @@
*/
mutex_lock(&pHddCtx->tdls_lock);
#endif
- hdd_deinit_adapter( pHddCtx, pAdapter );
+ hdd_deinit_adapter( pHddCtx, pAdapter, TRUE);
wdev->iftype = type;
//Check for sub-string p2p to confirm its a p2p interface
if (NULL != strstr(ndev->name,"p2p"))
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 57f3a8e..f072d20 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -58,6 +58,7 @@
#include <linux/wireless.h>
#include <linux/semaphore.h>
#include <linux/compat.h>
+#include <linux/rtnetlink.h>
#include <vos_api.h>
#include <vos_sched.h>
#include <linux/etherdevice.h>
@@ -262,7 +263,7 @@
if (pHostapdAdapter && pHostapdAdapter->pHddCtx)
{
- hdd_deinit_adapter(pHostapdAdapter->pHddCtx, pHostapdAdapter);
+ hdd_deinit_adapter(pHostapdAdapter->pHddCtx, pHostapdAdapter, TRUE);
/* after uninit our adapter structure will no longer be valid */
pHostapdAdapter->dev = NULL;
@@ -4884,7 +4885,7 @@
return status;
}
-VOS_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter)
+VOS_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter, tANI_U8 rtnl_held)
{
ENTER();
@@ -4895,7 +4896,16 @@
detatch the wireless device handlers */
if (pAdapter->dev)
{
- pAdapter->dev->wireless_handlers = NULL;
+ if (TRUE == rtnl_held)
+ {
+ pAdapter->dev->wireless_handlers = NULL;
+ }
+ else
+ {
+ rtnl_lock();
+ pAdapter->dev->wireless_handlers = NULL;
+ rtnl_unlock();
+ }
}
EXIT();
return 0;
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 6b5f3ae..746bbaf 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -5477,7 +5477,7 @@
mutex_lock(&pHddCtx->tdls_lock);
#endif
/* DeInit the adapter. This ensures datapath cleanup as well */
- hdd_deinit_adapter(pHddCtx, pAdapter);
+ hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
#ifdef FEATURE_WLAN_TDLS
mutex_unlock(&pHddCtx->tdls_lock);
#endif
@@ -5598,7 +5598,7 @@
#ifdef FEATURE_WLAN_TDLS
mutex_lock(&pHddCtx->tdls_lock);
#endif
- hdd_deinit_adapter(pHddCtx, pAdapter);
+ hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
#ifdef FEATURE_WLAN_TDLS
mutex_unlock(&pHddCtx->tdls_lock);
#endif
@@ -6302,7 +6302,7 @@
return;
}
-void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
+void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
{
ENTER();
switch ( pAdapter->device_mode )
@@ -6339,7 +6339,7 @@
hdd_cleanup_actionframe(pHddCtx, pAdapter);
- hdd_unregister_hostapd(pAdapter);
+ hdd_unregister_hostapd(pAdapter, rtnl_held);
hdd_set_conparam( 0 );
wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
break;
@@ -6717,7 +6717,7 @@
#ifdef FEATURE_WLAN_TDLS
mutex_lock(&pHddCtx->tdls_lock);
#endif
- hdd_deinit_adapter(pHddCtx, pAdapter);
+ hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
#ifdef FEATURE_WLAN_TDLS
mutex_unlock(&pHddCtx->tdls_lock);
#endif
@@ -6772,7 +6772,7 @@
status = hdd_register_hostapd( pAdapter, rtnl_held );
if( VOS_STATUS_SUCCESS != status )
{
- hdd_deinit_adapter(pHddCtx, pAdapter);
+ hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
goto err_free_netdev;
}
hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
@@ -8156,7 +8156,7 @@
#ifdef FEATURE_WLAN_TDLS
mutex_lock(&pHddCtx->tdls_lock);
#endif
- hdd_deinit_adapter(pHddCtx, pAdapter);
+ hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
#ifdef FEATURE_WLAN_TDLS
mutex_unlock(&pHddCtx->tdls_lock);
#endif
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index e8e8037..0e8da57 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -6747,7 +6747,7 @@
/*Make sure that pAdapter cleaned properly*/
hdd_stop_adapter( pHddCtx, pAdapter_to_stop, VOS_TRUE );
- hdd_deinit_adapter( pHddCtx, pAdapter_to_stop );
+ hdd_deinit_adapter( pHddCtx, pAdapter_to_stop, TRUE);
memset(&pAdapter_to_stop->sessionCtx, 0, sizeof(pAdapter_to_stop->sessionCtx));
wlan_hdd_release_intf_addr(WLAN_HDD_GET_CTX(pAdapter),