mac80211: fix monitor_sdata RCU/locking assertions
authorJohannes Berg <johannes.berg@intel.com>
Fri, 12 Nov 2021 12:51:44 +0000 (13:51 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Nov 2021 08:48:34 +0000 (09:48 +0100)
[ Upstream commit 6dd2360334f3cb3b45fc1b8194c670090474b87c ]

Since commit a05829a7222e ("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: a05829a7222e ("cfg80211: avoid holding the RTNL when calling the driver")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://lore.kernel.org/r/20211112135143.cb8e8ceffef3.Iaa210f16f6904c8a7a24954fb3396da0ef86ec08@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/mac80211/cfg.c
net/mac80211/iface.c
net/mac80211/util.c

index d69b31c..d3f62fd 100644 (file)
@@ -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))
@@ -810,7 +811,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,
@@ -2669,7 +2671,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;
                }
@@ -2729,7 +2732,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)
index 62c9559..041859b 100644 (file)
@@ -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;
        }
 
@@ -932,6 +932,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;
@@ -999,6 +1000,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
                return;
 
        ASSERT_RTNL();
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        mutex_lock(&local->iflist_mtx);
 
index 49cb96d..03ea4f9 100644 (file)
@@ -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))
@@ -2379,7 +2379,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);
@@ -2424,7 +2424,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);
        }