Skip to content

Commit

Permalink
wifi: mac80211: lock wiphy in IP address notifier
Browse files Browse the repository at this point in the history
[ Upstream commit 730538e ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
jmberg-intel authored and gregkh committed Aug 29, 2024
1 parent 5a002f4 commit f34056c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
14 changes: 14 additions & 0 deletions net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -2315,6 +2315,20 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
list_for_each_entry_safe(sdata, tmp, &unreg_list, list) {
bool netdev = sdata->dev;

/*
* Remove IP addresses explicitly, since the notifier will
* skip the callbacks if wdev->registered is false, since
* we can't acquire the wiphy_lock() again there if already
* inside this locked section.
*/
sdata_lock(sdata);
sdata->vif.cfg.arp_addr_cnt = 0;
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
sdata->u.mgd.associated)
ieee80211_vif_cfg_change_notify(sdata,
BSS_CHANGED_ARP_FILTER);
sdata_unlock(sdata);

list_del(&sdata->list);
cfg80211_unregister_wdev(&sdata->wdev);

Expand Down
22 changes: 21 additions & 1 deletion net/mac80211/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,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);
Expand All @@ -458,6 +458,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 */
Expand All @@ -476,6 +495,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;
}
Expand Down

0 comments on commit f34056c

Please sign in to comment.