Browse Source

qcacld-3.0: Check the netdev validity before deferencing it

If the netdevice registration fails, the netdevice is freed
by referencing the context in the adapter structure.
However, in some scenarios the registration failure can result
in the netdev ops uninit being called where the reference is
reset and hence invalid.

Fix this by saving the netdevice in a local variable

Change-Id: Id01bf5d3fe633432695520bda77697842ced9ff1
CRs-Fixed: 2423508
Madhvapathi Sriram 6 years ago
parent
commit
8b05665b74
1 changed files with 11 additions and 1 deletions
  1. 11 1
      core/hdd/src/wlan_hdd_main.c

+ 11 - 1
core/hdd/src/wlan_hdd_main.c

@@ -5006,6 +5006,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 				unsigned char name_assign_type,
 				bool rtnl_held)
 {
+	struct net_device *ndev = NULL;
 	struct hdd_adapter *adapter = NULL;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 
@@ -5069,6 +5070,8 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 			return NULL;
 		}
 
+		ndev = adapter->dev;
+
 		if (QDF_P2P_CLIENT_MODE == session_type)
 			adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
 		else if (QDF_P2P_DEVICE_MODE == session_type)
@@ -5125,6 +5128,8 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 			return NULL;
 		}
 
+		ndev = adapter->dev;
+
 		adapter->wdev.iftype =
 			(session_type ==
 			 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
@@ -5164,6 +5169,9 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 			hdd_err("Failed to allocate adapter for FTM mode");
 			return NULL;
 		}
+
+		ndev = adapter->dev;
+
 		adapter->wdev.iftype = NL80211_IFTYPE_STATION;
 		adapter->device_mode = session_type;
 		status = hdd_register_interface(adapter, rtnl_held);
@@ -5234,7 +5242,9 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 
 err_free_netdev:
 	wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes);
-	free_netdev(adapter->dev);
+
+	if (ndev)
+		free_netdev(ndev);
 
 	return NULL;
 }