linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf()
@ 2017-05-12 16:41 Brian Norris
  2017-05-12 16:41 ` [PATCH 02/11] mwifiex: Don't release tx_ba_stream_tbl_lock while iterating Brian Norris
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:41 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

If we fail to add an interface in mwifiex_add_virtual_intf(), we might
hit a BUG_ON() in the networking code, because we didn't tear things
down properly. Among the problems:

 (a) when failing to allocate workqueues, we fail to unregister the
     netdev before calling free_netdev()
 (b) even if we do try to unregister the netdev, we're still holding the
     rtnl lock, so the device never properly unregistered; we'll be at
     state NETREG_UNREGISTERING, and then hit free_netdev()'s:
	BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
 (c) we're allocating some dependent resources (e.g., DFS workqueues)
     after we've registered the interface; this may or may not cause
     problems, but it's good practice to allocate these before registering
 (d) we're not even trying to unwind anything when mwifiex_send_cmd() or
     mwifiex_sta_init_cmd() fail

To fix these issues, let's:

 * add a stacked set of error handling labels, to keep error handling
   consistent and properly ordered (resolving (a) and (d))
 * move the workqueue allocations before the registration (to resolve
   (c); also resolves (b) by avoiding error cases where we have to
   unregister)

[Incidentally, it's pretty easy to interrupt the alloc_workqueue() in,
e.g., the following:

  iw phy phy0 interface add mlan0 type station

by sending it SIGTERM.]

This bugfix covers commits like commit 7d652034d1a0 ("mwifiex: channel
switch support for mwifiex"), but parts of this bug exist all the way
back to the introduction of dynamic interface handling in commit
93a1df48d224 ("mwifiex: add cfg80211 handlers add/del_virtual_intf").

Cc: <stable@vger.kernel.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/cfg80211.c | 71 ++++++++++++-------------
 1 file changed, 35 insertions(+), 36 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 7ec06bf13413..025bc06a19d6 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -2964,10 +2964,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 	if (!dev) {
 		mwifiex_dbg(adapter, ERROR,
 			    "no memory available for netdevice\n");
-		memset(&priv->wdev, 0, sizeof(priv->wdev));
-		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-		return ERR_PTR(-ENOMEM);
+		ret = -ENOMEM;
+		goto err_alloc_netdev;
 	}
 
 	mwifiex_init_priv_params(priv, dev);
@@ -2976,11 +2974,11 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 	ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
 			       HostCmd_ACT_GEN_SET, 0, NULL, true);
 	if (ret)
-		return ERR_PTR(ret);
+		goto err_set_bss_mode;
 
 	ret = mwifiex_sta_init_cmd(priv, false, false);
 	if (ret)
-		return ERR_PTR(ret);
+		goto err_sta_init;
 
 	mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv);
 	if (adapter->is_hw_11ac_capable)
@@ -3011,31 +3009,14 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 
 	SET_NETDEV_DEV(dev, adapter->dev);
 
-	/* Register network device */
-	if (register_netdevice(dev)) {
-		mwifiex_dbg(adapter, ERROR,
-			    "cannot register virtual network device\n");
-		free_netdev(dev);
-		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-		priv->netdev = NULL;
-		memset(&priv->wdev, 0, sizeof(priv->wdev));
-		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-		return ERR_PTR(-EFAULT);
-	}
-
 	priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
 						  WQ_HIGHPRI |
 						  WQ_MEM_RECLAIM |
 						  WQ_UNBOUND, 1, name);
 	if (!priv->dfs_cac_workqueue) {
-		mwifiex_dbg(adapter, ERROR,
-			    "cannot register virtual network device\n");
-		free_netdev(dev);
-		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-		priv->netdev = NULL;
-		memset(&priv->wdev, 0, sizeof(priv->wdev));
-		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-		return ERR_PTR(-ENOMEM);
+		mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");
+		ret = -ENOMEM;
+		goto err_alloc_cac;
 	}
 
 	INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
@@ -3044,16 +3025,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 						      WQ_HIGHPRI | WQ_UNBOUND |
 						      WQ_MEM_RECLAIM, 1, name);
 	if (!priv->dfs_chan_sw_workqueue) {
-		mwifiex_dbg(adapter, ERROR,
-			    "cannot register virtual network device\n");
-		free_netdev(dev);
-		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
-		priv->netdev = NULL;
-		memset(&priv->wdev, 0, sizeof(priv->wdev));
-		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
-		destroy_workqueue(priv->dfs_cac_workqueue);
-		priv->dfs_cac_workqueue = NULL;
-		return ERR_PTR(-ENOMEM);
+		mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n");
+		ret = -ENOMEM;
+		goto err_alloc_chsw;
 	}
 
 	INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
@@ -3061,6 +3035,13 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 
 	sema_init(&priv->async_sem, 1);
 
+	/* Register network device */
+	if (register_netdevice(dev)) {
+		mwifiex_dbg(adapter, ERROR, "cannot register network device\n");
+		ret = -EFAULT;
+		goto err_reg_netdev;
+	}
+
 	mwifiex_dbg(adapter, INFO,
 		    "info: %s: Marvell 802.11 Adapter\n", dev->name);
 
@@ -3081,11 +3062,29 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 		adapter->curr_iface_comb.p2p_intf++;
 		break;
 	default:
+		/* This should be dead code; checked above */
 		mwifiex_dbg(adapter, ERROR, "type not supported\n");
 		return ERR_PTR(-EINVAL);
 	}
 
 	return &priv->wdev;
+
+err_reg_netdev:
+	destroy_workqueue(priv->dfs_chan_sw_workqueue);
+	priv->dfs_chan_sw_workqueue = NULL;
+err_alloc_chsw:
+	destroy_workqueue(priv->dfs_cac_workqueue);
+	priv->dfs_cac_workqueue = NULL;
+err_alloc_cac:
+	free_netdev(dev);
+	priv->netdev = NULL;
+err_sta_init:
+err_set_bss_mode:
+err_alloc_netdev:
+	memset(&priv->wdev, 0, sizeof(priv->wdev));
+	priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+	priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
 
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 02/11] mwifiex: Don't release tx_ba_stream_tbl_lock while iterating
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
@ 2017-05-12 16:41 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 03/11] mwifiex: Don't release cmd_pending_q_lock " Brian Norris
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:41 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

From: Douglas Anderson <dianders@chromium.org>

Despite the macro list_for_each_entry_safe() having the word "safe" in
the name, it's still not actually safe to release the list spinlock
while iterating over the list.  The "safe" in the macro name actually
only means that it's safe to delete the current entry while iterating
over the list.

Releasing the spinlock while iterating over the list means that someone
else could come in and adjust the list while we don't have the
spinlock.  If they do that it can totally mix up our iteration and fully
corrupt the list.  Later iterating over a corrupted list while holding a
spinlock and having IRQs off can cause all sorts of hard to debug
problems.

As evidenced by the other call to
mwifiex_11n_delete_tx_ba_stream_tbl_entry() in
mwifiex_11n_delete_all_tx_ba_stream_tbl(), it's actually safe to skip
the spinlock release.  Let's do that.

No known problems are fixed by this patch, but it could fix all sorts of
weird problems and it should be very safe.

Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/11n.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c
index c174e79e6df2..c75b6abf16a0 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n.c
@@ -764,14 +764,9 @@ void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
 		return;
 
 	spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-	list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) {
-		if (!memcmp(tbl->ra, ra, ETH_ALEN)) {
-			spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
-					       flags);
+	list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list)
+		if (!memcmp(tbl->ra, ra, ETH_ALEN))
 			mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
-			spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
-		}
-	}
 	spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
 
 	return;
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 03/11] mwifiex: Don't release cmd_pending_q_lock while iterating
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
  2017-05-12 16:41 ` [PATCH 02/11] mwifiex: Don't release tx_ba_stream_tbl_lock while iterating Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 04/11] mwifiex: Add locking to mwifiex_11n_delba Brian Norris
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

From: Douglas Anderson <dianders@chromium.org>

Just like in the previous patch ("mwifiex: Don't release
tx_ba_stream_tbl_lock while iterating"), in
mwifiex_cancel_all_pending_cmd() we were itearting over a list protected
by a spinlock.  Again, it is not safe to release the spinlock while
iterating.  Don't do it.

Luckily in this case there should be no need to release the spinlock.
This is evidenced by:

1. The only function called while the spinlock was released was
   mwifiex_recycle_cmd_node()
2. Aside from atomic functions (which are safe to call), the only
   function called by mwifiex_recycle_cmd_node() was
   mwifiex_insert_cmd_to_free_q().
3. It can be seen in mwifiex_cancel_pending_scan_cmd() that it's OK to
   call mwifiex_insert_cmd_to_free_q() while holding a different
   spinlock (scan_pending_q_lock), so in general holding a spinlock
   should be OK.
4. It doesn't appear that mwifiex_insert_cmd_to_free_q() has any
   interaction with the cmd_pending_q_lock

No known bugs are fixed with this change, but as with other similar
changes this could fix random list corruption.

Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/cmdevt.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 0c3b217247b1..5fd6c53d7b06 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -1056,12 +1056,10 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
 	list_for_each_entry_safe(cmd_node, tmp_node,
 				 &adapter->cmd_pending_q, list) {
 		list_del(&cmd_node->list);
-		spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
 
 		if (cmd_node->wait_q_enabled)
 			adapter->cmd_wait_q.status = -1;
 		mwifiex_recycle_cmd_node(adapter, cmd_node);
-		spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
 	}
 	spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
 	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 04/11] mwifiex: Add locking to mwifiex_11n_delba
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
  2017-05-12 16:41 ` [PATCH 02/11] mwifiex: Don't release tx_ba_stream_tbl_lock while iterating Brian Norris
  2017-05-12 16:42 ` [PATCH 03/11] mwifiex: Don't release cmd_pending_q_lock " Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 05/11] mwifiex: don't drop lock between list-retrieval / list-deletion Brian Norris
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

From: Douglas Anderson <dianders@chromium.org>

The mwifiex_11n_delba() function walked the rx_reorder_tbl_ptr without
holding the lock, which was an obvious violation.

Grab the lock.

NOTE: we hold the lock while calling mwifiex_send_delba().  There's also
several callers in 11n_rxreorder.c that hold the lock and the comments
in the struct sound just like very other list/lock pair -- as if the
lock should definitely be help for all operations like this.

Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/11n.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c
index c75b6abf16a0..16c77c27f1b6 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n.c
@@ -653,11 +653,13 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
 void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
 {
 	struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+	unsigned long flags;
 
+	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
 	if (list_empty(&priv->rx_reorder_tbl_ptr)) {
 		dev_dbg(priv->adapter->dev,
 			"mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
-		return;
+		goto exit;
 	}
 
 	list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
@@ -666,9 +668,11 @@ void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
 				"Send delba to tid=%d, %pM\n",
 				tid, rx_reor_tbl_ptr->ta);
 			mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0);
-			return;
+			goto exit;
 		}
 	}
+exit:
+	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
 }
 
 /*
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 05/11] mwifiex: don't drop lock between list-retrieval / list-deletion
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (2 preceding siblings ...)
  2017-05-12 16:42 ` [PATCH 04/11] mwifiex: Add locking to mwifiex_11n_delba Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 06/11] mwifiex: don't leak stashed beacon buffer on reset Brian Norris
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

mwifiex_exec_next_cmd() seems to have a classic TOCTOU race, where we
drop the list lock in between retrieving the next command and deleting
it from the list. This potentially leaves room for someone else to also
retrieve / steal this node from the list (e.g.,
mwifiex_cancel_all_pending_cmd()).

Let's keep holding the lock while we do our 'ps_state' sanity checks.
There should be no harm in continuing to hold this lock for a bit more.

Noticed only by code inspection.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/cmdevt.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 5fd6c53d7b06..95221306a4e5 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -761,8 +761,6 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
 	}
 	cmd_node = list_first_entry(&adapter->cmd_pending_q,
 				    struct cmd_ctrl_node, list);
-	spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
-			       cmd_pending_q_flags);
 
 	host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
 	priv = cmd_node->priv;
@@ -771,11 +769,12 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter)
 		mwifiex_dbg(adapter, ERROR,
 			    "%s: cannot send cmd in sleep state,\t"
 			    "this should not happen\n", __func__);
+		spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
+				       cmd_pending_q_flags);
 		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
 		return ret;
 	}
 
-	spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags);
 	list_del(&cmd_node->list);
 	spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
 			       cmd_pending_q_flags);
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 06/11] mwifiex: don't leak stashed beacon buffer on reset
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (3 preceding siblings ...)
  2017-05-12 16:42 ` [PATCH 05/11] mwifiex: don't drop lock between list-retrieval / list-deletion Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 07/11] mwifiex: remove useless 'mwifiex_lock' Brian Norris
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

When removing or resetting an mwifiex device, we don't remember to free
the saved beacon buffer. Use the (somewhat misleadingly-named)
mwifiex_free_priv() helper to handle this.

Noticed by kmemleak during tests:

echo 1 > /sys/bus/pci/devices/.../reset

unreferenced object 0xffffffc09d034a00 (size 256):
...
  backtrace:
    [<ffffffc0003cdce4>] create_object+0x228/0x3c4
    [<ffffffc000c0b9d8>] kmemleak_alloc+0x54/0x88
    [<ffffffc0003c0848>] __kmalloc+0x1cc/0x2dc
    [<ffffffbffc1500c4>] mwifiex_save_curr_bcn+0x80/0x308 [mwifiex]
    [<ffffffbffc1516b8>] mwifiex_ret_802_11_associate+0x4ec/0x5fc [mwifiex]
    [<ffffffbffc15da90>] mwifiex_process_sta_cmdresp+0xaf8/0x1fa4 [mwifiex]
    [<ffffffbffc1411e0>] mwifiex_process_cmdresp+0x40c/0x510 [mwifiex]
    [<ffffffbffc13b8f4>] mwifiex_main_process+0x4a4/0xb00 [mwifiex]
    [<ffffffbffc13bf84>] mwifiex_main_work_queue+0x34/0x40 [mwifiex]

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/init.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 756948385b60..2ada202c72ec 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -670,8 +670,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
 
 			mwifiex_clean_auto_tdls(priv);
 			mwifiex_abort_cac(priv);
-			mwifiex_clean_txrx(priv);
-			mwifiex_delete_bss_prio_tbl(priv);
+			mwifiex_free_priv(priv);
 		}
 	}
 
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 07/11] mwifiex: remove useless 'mwifiex_lock'
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (4 preceding siblings ...)
  2017-05-12 16:42 ` [PATCH 06/11] mwifiex: don't leak stashed beacon buffer on reset Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 08/11] mwifiex: remove redundant 'adapter' check in mwifiex_adapter_cleanup Brian Norris
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

If mwifiex_shutdown_drv() is racing with another mwifiex_shutdown_drv(),
we *really* have problems. Kill the lock.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/init.c | 4 ----
 drivers/net/wireless/marvell/mwifiex/main.h | 2 --
 2 files changed, 6 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 2ada202c72ec..2bff87bd76a6 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -439,7 +439,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
 	struct mwifiex_private *priv;
 	s32 i, j;
 
-	spin_lock_init(&adapter->mwifiex_lock);
 	spin_lock_init(&adapter->int_lock);
 	spin_lock_init(&adapter->main_proc_lock);
 	spin_lock_init(&adapter->mwifiex_cmd_lock);
@@ -693,11 +692,8 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
 
 	spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
 
-	spin_lock(&adapter->mwifiex_lock);
-
 	mwifiex_adapter_cleanup(adapter);
 
-	spin_unlock(&adapter->mwifiex_lock);
 	adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY;
 }
 
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index bb2a467d8b13..66c184936c95 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -870,8 +870,6 @@ struct mwifiex_adapter {
 	bool rx_locked;
 	bool main_locked;
 	struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM];
-	/* spin lock for init/shutdown */
-	spinlock_t mwifiex_lock;
 	/* spin lock for main process */
 	spinlock_t main_proc_lock;
 	u32 mwifiex_processing;
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 08/11] mwifiex: remove redundant 'adapter' check in mwifiex_adapter_cleanup
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (5 preceding siblings ...)
  2017-05-12 16:42 ` [PATCH 07/11] mwifiex: remove useless 'mwifiex_lock' Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 09/11] mwifiex: 11h: drop unnecessary check for '!priv' Brian Norris
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

We're using 'adapter' right before calling this. Stop being
unnecessarily paranoid.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/init.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index 2bff87bd76a6..80bdf1c5f77f 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -409,11 +409,6 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
 static void
 mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
 {
-	if (!adapter) {
-		pr_err("%s: adapter is NULL\n", __func__);
-		return;
-	}
-
 	del_timer(&adapter->wakeup_timer);
 	mwifiex_cancel_all_pending_cmd(adapter);
 	wake_up_interruptible(&adapter->cmd_wait_q.wait);
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 09/11] mwifiex: 11h: drop unnecessary check for '!priv'
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (6 preceding siblings ...)
  2017-05-12 16:42 ` [PATCH 08/11] mwifiex: remove redundant 'adapter' check in mwifiex_adapter_cleanup Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 10/11] mwifiex: pcie: remove useless pdev check Brian Norris
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

These pointers are retrieved via container_of(). There's no way they are
NULL.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/11h.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c
index 366eb4991a7d..238accfe4f41 100644
--- a/drivers/net/wireless/marvell/mwifiex/11h.c
+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
@@ -128,9 +128,6 @@ void mwifiex_dfs_cac_work_queue(struct work_struct *work)
 			container_of(delayed_work, struct mwifiex_private,
 				     dfs_cac_work);
 
-	if (WARN_ON(!priv))
-		return;
-
 	chandef = priv->dfs_chandef;
 	if (priv->wdev.cac_started) {
 		mwifiex_dbg(priv->adapter, MSG,
@@ -289,9 +286,6 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
 			container_of(delayed_work, struct mwifiex_private,
 				     dfs_chan_sw_work);
 
-	if (WARN_ON(!priv))
-		return;
-
 	bss_cfg = &priv->bss_cfg;
 	if (!bss_cfg->beacon_period) {
 		mwifiex_dbg(priv->adapter, ERROR,
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 10/11] mwifiex: pcie: remove useless pdev check
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (7 preceding siblings ...)
  2017-05-12 16:42 ` [PATCH 09/11] mwifiex: 11h: drop unnecessary check for '!priv' Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-12 16:42 ` [PATCH 11/11] mwifiex: pcie: stop setting/clearing 'surprise_removed' Brian Norris
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index ac62bce50e96..d7e563a622f7 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2380,11 +2380,6 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
 	struct pcie_service_card *card;
 	struct mwifiex_adapter *adapter;
 
-	if (!pdev) {
-		pr_err("info: %s: pdev is NULL\n", __func__);
-		goto exit;
-	}
-
 	card = pci_get_drvdata(pdev);
 
 	if (!card->adapter) {
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 11/11] mwifiex: pcie: stop setting/clearing 'surprise_removed'
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (8 preceding siblings ...)
  2017-05-12 16:42 ` [PATCH 10/11] mwifiex: pcie: remove useless pdev check Brian Norris
@ 2017-05-12 16:42 ` Brian Norris
  2017-05-17  4:02 ` [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Xinming Hu
  2017-05-19  6:02 ` [01/11] " Kalle Valo
  11 siblings, 0 replies; 13+ messages in thread
From: Brian Norris @ 2017-05-12 16:42 UTC (permalink / raw)
  To: Ganapathi Bhat, Nishant Sarmukadam
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson, Brian Norris

These are already handled by mwifiex_shutdown_sw() and
mwifiex_reinit_sw(). Ideally, we'll kill the flag entirely eventually,
as I suspect it breeds race conditions.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index d7e563a622f7..da042d15f8f0 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -370,7 +370,6 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
 		 * PCIe and HW.
 		 */
 		mwifiex_shutdown_sw(adapter);
-		adapter->surprise_removed = true;
 		clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
 		clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
 	} else {
@@ -378,7 +377,6 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
 		 * after performing FLR respectively. Reconfigure the software
 		 * and firmware including firmware redownload
 		 */
-		adapter->surprise_removed = false;
 		ret = mwifiex_reinit_sw(adapter);
 		if (ret) {
 			dev_err(&pdev->dev, "reinit failed: %d\n", ret);
-- 
2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* RE: [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf()
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (9 preceding siblings ...)
  2017-05-12 16:42 ` [PATCH 11/11] mwifiex: pcie: stop setting/clearing 'surprise_removed' Brian Norris
@ 2017-05-17  4:02 ` Xinming Hu
  2017-05-19  6:02 ` [01/11] " Kalle Valo
  11 siblings, 0 replies; 13+ messages in thread
From: Xinming Hu @ 2017-05-17  4:02 UTC (permalink / raw)
  To: Brian Norris, Ganapathi Bhat, Nishant Sarmukadam, Cathy Luo
  Cc: linux-kernel, Dmitry Torokhov, Amitkumar Karwar, Kalle Valo,
	linux-wireless, Doug Anderson

Hi,

This patch serials looks fine, thanks.

> -----Original Message-----
> From: linux-wireless-owner@vger.kernel.org
> [mailto:linux-wireless-owner@vger.kernel.org] On Behalf Of Brian Norris
> Sent: 2017年5月13日 0:42
> To: Ganapathi Bhat; Nishant Sarmukadam
> Cc: linux-kernel@vger.kernel.org; Dmitry Torokhov; Amitkumar Karwar; Kalle
> Valo; linux-wireless@vger.kernel.org; Doug Anderson; Brian Norris
> Subject: [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf()
> 
> If we fail to add an interface in mwifiex_add_virtual_intf(), we might hit a
> BUG_ON() in the networking code, because we didn't tear things down
> properly. Among the problems:
> 
>  (a) when failing to allocate workqueues, we fail to unregister the
>      netdev before calling free_netdev()
>  (b) even if we do try to unregister the netdev, we're still holding the
>      rtnl lock, so the device never properly unregistered; we'll be at
>      state NETREG_UNREGISTERING, and then hit free_netdev()'s:
> 	BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
>  (c) we're allocating some dependent resources (e.g., DFS workqueues)
>      after we've registered the interface; this may or may not cause
>      problems, but it's good practice to allocate these before registering
>  (d) we're not even trying to unwind anything when mwifiex_send_cmd() or
>      mwifiex_sta_init_cmd() fail
> 
> To fix these issues, let's:
> 
>  * add a stacked set of error handling labels, to keep error handling
>    consistent and properly ordered (resolving (a) and (d))
>  * move the workqueue allocations before the registration (to resolve
>    (c); also resolves (b) by avoiding error cases where we have to
>    unregister)
> 
> [Incidentally, it's pretty easy to interrupt the alloc_workqueue() in, e.g., the
> following:
> 
>   iw phy phy0 interface add mlan0 type station
> 
> by sending it SIGTERM.]
> 
> This bugfix covers commits like commit 7d652034d1a0 ("mwifiex: channel
> switch support for mwifiex"), but parts of this bug exist all the way back to the
> introduction of dynamic interface handling in commit
> 93a1df48d224 ("mwifiex: add cfg80211 handlers add/del_virtual_intf").
> 
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---
>  drivers/net/wireless/marvell/mwifiex/cfg80211.c | 71
> ++++++++++++-------------
>  1 file changed, 35 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> index 7ec06bf13413..025bc06a19d6 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> @@ -2964,10 +2964,8 @@ struct wireless_dev
> *mwifiex_add_virtual_intf(struct wiphy *wiphy,
>  	if (!dev) {
>  		mwifiex_dbg(adapter, ERROR,
>  			    "no memory available for netdevice\n");
> -		memset(&priv->wdev, 0, sizeof(priv->wdev));
> -		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
> -		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
> -		return ERR_PTR(-ENOMEM);
> +		ret = -ENOMEM;
> +		goto err_alloc_netdev;
>  	}
> 
>  	mwifiex_init_priv_params(priv, dev);
> @@ -2976,11 +2974,11 @@ struct wireless_dev
> *mwifiex_add_virtual_intf(struct wiphy *wiphy,
>  	ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
>  			       HostCmd_ACT_GEN_SET, 0, NULL, true);
>  	if (ret)
> -		return ERR_PTR(ret);
> +		goto err_set_bss_mode;
> 
>  	ret = mwifiex_sta_init_cmd(priv, false, false);
>  	if (ret)
> -		return ERR_PTR(ret);
> +		goto err_sta_init;
> 
>  	mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap,
> priv);
>  	if (adapter->is_hw_11ac_capable)
> @@ -3011,31 +3009,14 @@ struct wireless_dev
> *mwifiex_add_virtual_intf(struct wiphy *wiphy,
> 
>  	SET_NETDEV_DEV(dev, adapter->dev);
> 
> -	/* Register network device */
> -	if (register_netdevice(dev)) {
> -		mwifiex_dbg(adapter, ERROR,
> -			    "cannot register virtual network device\n");
> -		free_netdev(dev);
> -		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
> -		priv->netdev = NULL;
> -		memset(&priv->wdev, 0, sizeof(priv->wdev));
> -		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
> -		return ERR_PTR(-EFAULT);
> -	}
> -
>  	priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
>  						  WQ_HIGHPRI |
>  						  WQ_MEM_RECLAIM |
>  						  WQ_UNBOUND, 1, name);
>  	if (!priv->dfs_cac_workqueue) {
> -		mwifiex_dbg(adapter, ERROR,
> -			    "cannot register virtual network device\n");
> -		free_netdev(dev);
> -		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
> -		priv->netdev = NULL;
> -		memset(&priv->wdev, 0, sizeof(priv->wdev));
> -		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
> -		return ERR_PTR(-ENOMEM);
> +		mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");
> +		ret = -ENOMEM;
> +		goto err_alloc_cac;
>  	}
> 
>  	INIT_DELAYED_WORK(&priv->dfs_cac_work,
> mwifiex_dfs_cac_work_queue); @@ -3044,16 +3025,9 @@ struct wireless_dev
> *mwifiex_add_virtual_intf(struct wiphy *wiphy,
>  						      WQ_HIGHPRI | WQ_UNBOUND |
>  						      WQ_MEM_RECLAIM, 1, name);
>  	if (!priv->dfs_chan_sw_workqueue) {
> -		mwifiex_dbg(adapter, ERROR,
> -			    "cannot register virtual network device\n");
> -		free_netdev(dev);
> -		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
> -		priv->netdev = NULL;
> -		memset(&priv->wdev, 0, sizeof(priv->wdev));
> -		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
> -		destroy_workqueue(priv->dfs_cac_workqueue);
> -		priv->dfs_cac_workqueue = NULL;
> -		return ERR_PTR(-ENOMEM);
> +		mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw
> queue\n");
> +		ret = -ENOMEM;
> +		goto err_alloc_chsw;
>  	}
> 
>  	INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
> @@ -3061,6 +3035,13 @@ struct wireless_dev
> *mwifiex_add_virtual_intf(struct wiphy *wiphy,
> 
>  	sema_init(&priv->async_sem, 1);
> 
> +	/* Register network device */
> +	if (register_netdevice(dev)) {
> +		mwifiex_dbg(adapter, ERROR, "cannot register network device\n");
> +		ret = -EFAULT;
> +		goto err_reg_netdev;
> +	}
> +
>  	mwifiex_dbg(adapter, INFO,
>  		    "info: %s: Marvell 802.11 Adapter\n", dev->name);
> 
> @@ -3081,11 +3062,29 @@ struct wireless_dev
> *mwifiex_add_virtual_intf(struct wiphy *wiphy,
>  		adapter->curr_iface_comb.p2p_intf++;
>  		break;
>  	default:
> +		/* This should be dead code; checked above */
>  		mwifiex_dbg(adapter, ERROR, "type not supported\n");
>  		return ERR_PTR(-EINVAL);
>  	}
> 
>  	return &priv->wdev;
> +
> +err_reg_netdev:
> +	destroy_workqueue(priv->dfs_chan_sw_workqueue);
> +	priv->dfs_chan_sw_workqueue = NULL;
> +err_alloc_chsw:
> +	destroy_workqueue(priv->dfs_cac_workqueue);
> +	priv->dfs_cac_workqueue = NULL;
> +err_alloc_cac:
> +	free_netdev(dev);
> +	priv->netdev = NULL;
> +err_sta_init:
> +err_set_bss_mode:
> +err_alloc_netdev:
> +	memset(&priv->wdev, 0, sizeof(priv->wdev));
> +	priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
> +	priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
> +	return ERR_PTR(ret);
>  }
>  EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
> 

Regards,
Simon

> --
> 2.13.0.rc2.291.g57267f2277-goog

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf()
  2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
                   ` (10 preceding siblings ...)
  2017-05-17  4:02 ` [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Xinming Hu
@ 2017-05-19  6:02 ` Kalle Valo
  11 siblings, 0 replies; 13+ messages in thread
From: Kalle Valo @ 2017-05-19  6:02 UTC (permalink / raw)
  To: Brian Norris
  Cc: Ganapathi Bhat, Nishant Sarmukadam, linux-kernel,
	Dmitry Torokhov, Amitkumar Karwar, linux-wireless, Doug Anderson,
	Brian Norris

Brian Norris <briannorris@chromium.org> wrote:
> If we fail to add an interface in mwifiex_add_virtual_intf(), we might
> hit a BUG_ON() in the networking code, because we didn't tear things
> down properly. Among the problems:
> 
>  (a) when failing to allocate workqueues, we fail to unregister the
>      netdev before calling free_netdev()
>  (b) even if we do try to unregister the netdev, we're still holding the
>      rtnl lock, so the device never properly unregistered; we'll be at
>      state NETREG_UNREGISTERING, and then hit free_netdev()'s:
> 	BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
>  (c) we're allocating some dependent resources (e.g., DFS workqueues)
>      after we've registered the interface; this may or may not cause
>      problems, but it's good practice to allocate these before registering
>  (d) we're not even trying to unwind anything when mwifiex_send_cmd() or
>      mwifiex_sta_init_cmd() fail
> 
> To fix these issues, let's:
> 
>  * add a stacked set of error handling labels, to keep error handling
>    consistent and properly ordered (resolving (a) and (d))
>  * move the workqueue allocations before the registration (to resolve
>    (c); also resolves (b) by avoiding error cases where we have to
>    unregister)
> 
> [Incidentally, it's pretty easy to interrupt the alloc_workqueue() in,
> e.g., the following:
> 
>   iw phy phy0 interface add mlan0 type station
> 
> by sending it SIGTERM.]
> 
> This bugfix covers commits like commit 7d652034d1a0 ("mwifiex: channel
> switch support for mwifiex"), but parts of this bug exist all the way
> back to the introduction of dynamic interface handling in commit
> 93a1df48d224 ("mwifiex: add cfg80211 handlers add/del_virtual_intf").
> 
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Brian Norris <briannorris@chromium.org>

11 patches applied to wireless-drivers-next.git, thanks.

8535107aa4ef mwifiex: fixup error cases in mwifiex_add_virtual_intf()
e0b636e5ee15 mwifiex: Don't release tx_ba_stream_tbl_lock while iterating
90ad0be83676 mwifiex: Don't release cmd_pending_q_lock while iterating
09bdb6500551 mwifiex: Add locking to mwifiex_11n_delba
0f13acf0c612 mwifiex: don't drop lock between list-retrieval / list-deletion
6eb2d002d4ea mwifiex: don't leak stashed beacon buffer on reset
bc69ca391eff mwifiex: remove useless 'mwifiex_lock'
7170862738dc mwifiex: remove redundant 'adapter' check in mwifiex_adapter_cleanup
7ade530e7384 mwifiex: 11h: drop unnecessary check for '!priv'
fa4651e12ae8 mwifiex: pcie: remove useless pdev check
68efd0386988 mwifiex: pcie: stop setting/clearing 'surprise_removed'

-- 
https://patchwork.kernel.org/patch/9724599/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-05-19  6:02 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-12 16:41 [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Brian Norris
2017-05-12 16:41 ` [PATCH 02/11] mwifiex: Don't release tx_ba_stream_tbl_lock while iterating Brian Norris
2017-05-12 16:42 ` [PATCH 03/11] mwifiex: Don't release cmd_pending_q_lock " Brian Norris
2017-05-12 16:42 ` [PATCH 04/11] mwifiex: Add locking to mwifiex_11n_delba Brian Norris
2017-05-12 16:42 ` [PATCH 05/11] mwifiex: don't drop lock between list-retrieval / list-deletion Brian Norris
2017-05-12 16:42 ` [PATCH 06/11] mwifiex: don't leak stashed beacon buffer on reset Brian Norris
2017-05-12 16:42 ` [PATCH 07/11] mwifiex: remove useless 'mwifiex_lock' Brian Norris
2017-05-12 16:42 ` [PATCH 08/11] mwifiex: remove redundant 'adapter' check in mwifiex_adapter_cleanup Brian Norris
2017-05-12 16:42 ` [PATCH 09/11] mwifiex: 11h: drop unnecessary check for '!priv' Brian Norris
2017-05-12 16:42 ` [PATCH 10/11] mwifiex: pcie: remove useless pdev check Brian Norris
2017-05-12 16:42 ` [PATCH 11/11] mwifiex: pcie: stop setting/clearing 'surprise_removed' Brian Norris
2017-05-17  4:02 ` [PATCH 01/11] mwifiex: fixup error cases in mwifiex_add_virtual_intf() Xinming Hu
2017-05-19  6:02 ` [01/11] " Kalle Valo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).