mwifiex: failure path handling in mwifiex_add_virtual_intf()
authorAmitkumar Karwar <akarwar@marvell.com>
Fri, 15 Nov 2013 03:10:38 +0000 (19:10 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 15 Nov 2013 19:29:31 +0000 (14:29 -0500)
1) If register_netdevice() is failed, we are freeing netdev
pointer, but priv->netdev is not cleared. This gives kernel
paging request error when driver is unloaded or interface is
deleted. Fix the problem by clearing the pointer.
2) Fix memory leak issue by freeing 'wdev' in failure paths.
Also, clear priv->wdev pointer.

As mwifiex_add_virtual_intf() successfully handles the
failure conditions, redundant code under err_add_intf label
is removed in this patch.

Reported-by: Ujjal Roy <royujjal@gmail.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/main.c

index fbad00a5abc83502c3a16a7762f05bf6dcccf36a..ccc9c0866b25f00aa93b4afdd7df05ce6cbc1179 100644 (file)
@@ -2210,8 +2210,10 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                priv->bss_started = 0;
                priv->bss_num = 0;
 
-               if (mwifiex_cfg80211_init_p2p_client(priv))
-                       return ERR_PTR(-EFAULT);
+               if (mwifiex_cfg80211_init_p2p_client(priv)) {
+                       wdev = ERR_PTR(-EFAULT);
+                       goto done;
+               }
 
                break;
        default:
@@ -2224,7 +2226,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
        if (!dev) {
                wiphy_err(wiphy, "no memory available for netdevice\n");
                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-ENOMEM);
+               wdev = ERR_PTR(-ENOMEM);
+               goto done;
        }
 
        mwifiex_init_priv_params(priv, dev);
@@ -2264,7 +2267,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                wiphy_err(wiphy, "cannot register virtual network device\n");
                free_netdev(dev);
                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-               return ERR_PTR(-EFAULT);
+               priv->netdev = NULL;
+               wdev = ERR_PTR(-EFAULT);
+               goto done;
        }
 
        sema_init(&priv->async_sem, 1);
@@ -2274,6 +2279,13 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 #ifdef CONFIG_DEBUG_FS
        mwifiex_dev_debugfs_init(priv);
 #endif
+
+done:
+       if (IS_ERR(wdev)) {
+               kfree(priv->wdev);
+               priv->wdev = NULL;
+       }
+
        return wdev;
 }
 EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
index 7c7da3ea55a964a99af11106fd17a3fad85afb9f..9236b42007fb05268853c9fa9781568cfb6b288f 100644 (file)
@@ -411,7 +411,7 @@ static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
  */
 static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
 {
-       int ret, i;
+       int ret;
        char fmt[64];
        struct mwifiex_private *priv;
        struct mwifiex_adapter *adapter = context;
@@ -479,6 +479,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
                                        NL80211_IFTYPE_STATION, NULL, NULL);
        if (IS_ERR(wdev)) {
                dev_err(adapter->dev, "cannot create default STA interface\n");
+               rtnl_unlock();
                goto err_add_intf;
        }
        rtnl_unlock();
@@ -488,16 +489,6 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
        goto done;
 
 err_add_intf:
-       for (i = 0; i < adapter->priv_num; i++) {
-               priv = adapter->priv[i];
-
-               if (!priv)
-                       continue;
-
-               if (priv->wdev && priv->netdev)
-                       mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
-       }
-       rtnl_unlock();
 err_register_cfg80211:
        wiphy_unregister(adapter->wiphy);
        wiphy_free(adapter->wiphy);