diff mbox series

[6.6] Revert "wifi: mac80211: fix RCU list iterations"

Message ID 20241109171430.1640793-1-pchelkin@ispras.ru (mailing list archive)
State Not Applicable
Delegated to: Johannes Berg
Headers show
Series [6.6] Revert "wifi: mac80211: fix RCU list iterations" | expand

Commit Message

Fedor Pchelkin Nov. 9, 2024, 5:14 p.m. UTC
This reverts commit f37319609335d3eb2f7edfec4bad7996668a4d29 which is
commit ac35180032fbc5d80b29af00ba4881815ceefcb6 upstream.

The reverted commit is based heavily on wiphy locking changes made by the
"wifi: cfg80211/mac80211: locking cleanups" series [1] introduced since
6.7 kernel and not supposed to be backported to old stable branches.

It breaks locking rules in the context of old stables leading e.g. to the
following lockdep splat there - ieee80211_get_max_required_bw() is
actually called under RCU reader lock in 6.1/6.6, not the wiphy mutex.

WARNING: CPU: 3 PID: 8711 at net/mac80211/chan.c:248 ieee80211_get_max_required_bw+0x423/0x4e0 net/mac80211/chan.c:248
Modules linked in:
CPU: 3 PID: 8711 Comm: kworker/u8:6 Not tainted 6.1.113-syzkaller-00105-g9859ec205cfa #0
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
Workqueue: phy155 ieee80211_iface_work
RIP: 0010:ieee80211_get_max_required_bw+0x423/0x4e0 net/mac80211/chan.c:248
Call Trace:
 <TASK>
 ieee80211_get_chanctx_vif_max_required_bw net/mac80211/chan.c:294 [inline]
 ieee80211_get_chanctx_max_required_bw net/mac80211/chan.c:336 [inline]
 _ieee80211_recalc_chanctx_min_def+0x5e6/0xf30 net/mac80211/chan.c:381
 ieee80211_recalc_chanctx_min_def+0x21/0x80 net/mac80211/chan.c:462
 ieee80211_recalc_min_chandef+0x17a/0x590 net/mac80211/util.c:2908
 sta_info_move_state+0x748/0x8c0 net/mac80211/sta_info.c:2301
 ieee80211_assoc_success net/mac80211/mlme.c:5001 [inline]
 ieee80211_rx_mgmt_assoc_resp.cold+0x1335/0x69ec net/mac80211/mlme.c:5201
 ieee80211_sta_rx_queued_mgmt+0x40f/0x2270 net/mac80211/mlme.c:5831
 ieee80211_iface_process_skb net/mac80211/iface.c:1665 [inline]
 ieee80211_iface_work+0xa31/0xd30 net/mac80211/iface.c:1722
 process_one_work+0xa72/0x1590 kernel/workqueue.c:2292
 worker_thread+0x632/0x1240 kernel/workqueue.c:2439
 kthread+0x2e1/0x3a0 kernel/kthread.c:376
 ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:295

[1]: https://lore.kernel.org/linux-wireless/20230828115927.116700-41-johannes@sipsolutions.net/

Found by Linux Verification Center (linuxtesting.org) with Syzkaller.

Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
---
 net/mac80211/chan.c | 4 +---
 net/mac80211/mlme.c | 2 +-
 net/mac80211/scan.c | 2 +-
 net/mac80211/util.c | 4 +---
 4 files changed, 4 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index c09aed6a3cfc..68952752b599 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -245,9 +245,7 @@  ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata,
 	enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
 	struct sta_info *sta;
 
-	lockdep_assert_wiphy(sdata->local->hw.wiphy);
-
-	list_for_each_entry(sta, &sdata->local->sta_list, list) {
+	list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
 		if (sdata != sta->sdata &&
 		    !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
 			continue;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b14c809bcdea..42e2c84ed248 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -732,7 +732,7 @@  static bool ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
 		bool disable_mu_mimo = false;
 		struct ieee80211_sub_if_data *other;
 
-		list_for_each_entry(other, &local->interfaces, list) {
+		list_for_each_entry_rcu(other, &local->interfaces, list) {
 			if (other->vif.bss_conf.mu_mimo_owner) {
 				disable_mu_mimo = true;
 				break;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index d4a032f34577..1726e3221d3c 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -490,7 +490,7 @@  static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
 	 * the scan was in progress; if there was none this will
 	 * just be a no-op for the particular interface.
 	 */
-	list_for_each_entry(sdata, &local->interfaces, list) {
+	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 		if (ieee80211_sdata_running(sdata))
 			wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
 	}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 02b5aaad2a15..d682c32821a1 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -745,9 +745,7 @@  static void __iterate_interfaces(struct ieee80211_local *local,
 	struct ieee80211_sub_if_data *sdata;
 	bool active_only = iter_flags & IEEE80211_IFACE_ITER_ACTIVE;
 
-	list_for_each_entry_rcu(sdata, &local->interfaces, list,
-				lockdep_is_held(&local->iflist_mtx) ||
-				lockdep_is_held(&local->hw.wiphy->mtx)) {
+	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 		switch (sdata->vif.type) {
 		case NL80211_IFTYPE_MONITOR:
 			if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))