Blob Blame History Raw
From e0b636e5ee15558c6240fa8738f2b608c07ea17a Mon Sep 17 00:00:00 2001
From: Douglas Anderson <dianders@chromium.org>
Date: Fri, 12 May 2017 09:41:59 -0700
Subject: [PATCH] mwifiex: Don't release tx_ba_stream_tbl_lock while iterating
Git-commit: e0b636e5ee15558c6240fa8738f2b608c07ea17a
Patch-mainline: v4.13-rc1
References: FATE#326294

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>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 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.19.2