summaryrefslogtreecommitdiff
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2023-08-28 13:59:41 +0200
committerJohannes Berg <johannes.berg@intel.com>2023-09-11 11:27:20 +0200
commit730538edc8e0eb14b02708f65100a0deaf43e6cd (patch)
tree265419703478bc1b65afd93f0021e677443ac876 /net/mac80211/main.c
parentac2f7d6f2765a10b5075e0024706df7e845e7890 (diff)
wifi: mac80211: lock wiphy in IP address notifier
Lock the wiphy in the IP address notifier as another place that should have it locked before calling into the driver. This needs a bit of attention since the notifier can be called while the wiphy is already locked, when we remove an interface. Handle this by not running the notifier in this case, and instead calling out to the driver directly. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b6c089648441..f6860889fbdd 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -437,7 +437,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
if (!wdev)
return NOTIFY_DONE;
- if (wdev->wiphy != local->hw.wiphy)
+ if (wdev->wiphy != local->hw.wiphy || !wdev->registered)
return NOTIFY_DONE;
sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
@@ -452,6 +452,25 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
return NOTIFY_DONE;
ifmgd = &sdata->u.mgd;
+
+ /*
+ * The nested here is needed to convince lockdep that this is
+ * all OK. Yes, we lock the wiphy mutex here while we already
+ * hold the notifier rwsem, that's the normal case. And yes,
+ * we also acquire the notifier rwsem again when unregistering
+ * a netdev while we already hold the wiphy mutex, so it does
+ * look like a typical ABBA deadlock.
+ *
+ * However, both of these things happen with the RTNL held
+ * already. Therefore, they can't actually happen, since the
+ * lock orders really are ABC and ACB, which is fine due to
+ * the RTNL (A).
+ *
+ * We still need to prevent recursion, which is accomplished
+ * by the !wdev->registered check above.
+ */
+ mutex_lock_nested(&local->hw.wiphy->mtx, 1);
+ __acquire(&local->hw.wiphy->mtx);
sdata_lock(sdata);
/* Copy the addresses to the vif config list */
@@ -470,6 +489,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_ARP_FILTER);
sdata_unlock(sdata);
+ wiphy_unlock(local->hw.wiphy);
return NOTIFY_OK;
}