Commit 6dd23603 authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: fix monitor_sdata RCU/locking assertions



Since commit a05829a7 ("cfg80211: avoid holding the RTNL when
calling the driver") we've not only been protecting the pointer
to monitor_sdata with the RTNL, but also with the wiphy->mtx. This
is relevant in a number of lockdep assertions, e.g. the one we hit
in ieee80211_set_monitor_channel(). However, we're now protecting
all the assignments/dereferences, even the one in interface iter,
with the wiphy->mtx, so switch over the lockdep assertions to that
lock.

Fixes: a05829a7 ("cfg80211: avoid holding the RTNL when calling the driver")
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Link: https://lore.kernel.org/r/20211112135143.cb8e8ceffef3.Iaa210f16f6904c8a7a24954fb3396da0ef86ec08@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent f6ab25d4
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
	}

	/* also validate MU-MIMO change */
	monitor_sdata = rtnl_dereference(local->monitor_sdata);
	monitor_sdata = wiphy_dereference(local->hw.wiphy,
					  local->monitor_sdata);

	if (!monitor_sdata &&
	    (params->vht_mumimo_groups || params->vht_mumimo_follow_addr))
@@ -840,7 +841,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,

	mutex_lock(&local->mtx);
	if (local->use_chanctx) {
		sdata = rtnl_dereference(local->monitor_sdata);
		sdata = wiphy_dereference(local->hw.wiphy,
					  local->monitor_sdata);
		if (sdata) {
			ieee80211_vif_release_channel(sdata);
			ret = ieee80211_vif_use_channel(sdata, chandef,
@@ -2707,7 +2709,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
		sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);

		if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
			sdata = rtnl_dereference(local->monitor_sdata);
			sdata = wiphy_dereference(local->hw.wiphy,
						  local->monitor_sdata);
			if (!sdata)
				return -EOPNOTSUPP;
		}
@@ -2767,7 +2770,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
	mutex_unlock(&local->iflist_mtx);

	if (has_monitor) {
		sdata = rtnl_dereference(local->monitor_sdata);
		sdata = wiphy_dereference(local->hw.wiphy,
					  local->monitor_sdata);
		if (sdata) {
			sdata->user_power_level = local->user_power_level;
			if (txp_type != sdata->vif.bss_conf.txpower_type)
+3 −1
Original line number Diff line number Diff line
@@ -588,7 +588,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
	 */
	if (local->suspended) {
		WARN_ON(local->wowlan);
		WARN_ON(rtnl_dereference(local->monitor_sdata));
		WARN_ON(rcu_access_pointer(local->monitor_sdata));
		return;
	}

@@ -961,6 +961,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
		return 0;

	ASSERT_RTNL();
	lockdep_assert_wiphy(local->hw.wiphy);

	if (local->monitor_sdata)
		return 0;
@@ -1028,6 +1029,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
		return;

	ASSERT_RTNL();
	lockdep_assert_wiphy(local->hw.wiphy);

	mutex_lock(&local->iflist_mtx);

+4 −3
Original line number Diff line number Diff line
@@ -796,7 +796,7 @@ static void __iterate_interfaces(struct ieee80211_local *local,

	sdata = rcu_dereference_check(local->monitor_sdata,
				      lockdep_is_held(&local->iflist_mtx) ||
				      lockdep_rtnl_is_held());
				      lockdep_is_held(&local->hw.wiphy->mtx));
	if (sdata &&
	    (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only ||
	     sdata->flags & IEEE80211_SDATA_IN_DRIVER))
@@ -2381,7 +2381,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
				   IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);

	/* add interfaces */
	sdata = rtnl_dereference(local->monitor_sdata);
	sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
	if (sdata) {
		/* in HW restart it exists already */
		WARN_ON(local->resuming);
@@ -2426,7 +2426,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
				WARN_ON(drv_add_chanctx(local, ctx));
		mutex_unlock(&local->chanctx_mtx);

		sdata = rtnl_dereference(local->monitor_sdata);
		sdata = wiphy_dereference(local->hw.wiphy,
					  local->monitor_sdata);
		if (sdata && ieee80211_sdata_running(sdata))
			ieee80211_assign_chanctx(local, sdata);
	}