OSDN Git Service

wifi: mac80211: sta_info: fix link_sta insertion
authorJohannes Berg <johannes.berg@intel.com>
Tue, 19 Jul 2022 10:08:29 +0000 (12:08 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 22 Jul 2022 12:28:19 +0000 (14:28 +0200)
When inserting a link STA, make sure it doesn't exist first
and add lockdep assertions that we cannot modify the hash
table without holding the sta_mtx, so this check is really
correct.

Also return without hashing if the driver failed, and warn
if the hashing fails, which shouldn't happen due to the
check described above.

Fixes: cb71f1d136a6 ("wifi: mac80211: add sta link addition/removal")
Fixes: ba6ddab94fc6 ("wifi: mac80211: maintain link-sta hash table")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/sta_info.c

index 44e21de..cb23da9 100644 (file)
@@ -99,6 +99,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
 static int link_sta_info_hash_add(struct ieee80211_local *local,
                                  struct link_sta_info *link_sta)
 {
+       lockdep_assert_held(&local->sta_mtx);
        return rhltable_insert(&local->link_sta_hash,
                               &link_sta->link_hash_node,
                               link_sta_rht_params);
@@ -107,6 +108,7 @@ static int link_sta_info_hash_add(struct ieee80211_local *local,
 static int link_sta_info_hash_del(struct ieee80211_local *local,
                                  struct link_sta_info *link_sta)
 {
+       lockdep_assert_held(&local->sta_mtx);
        return rhltable_remove(&local->link_sta_hash,
                               &link_sta->link_hash_node,
                               link_sta_rht_params);
@@ -2765,6 +2767,14 @@ int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id)
        if (WARN_ON(old_links == new_links || !link_sta))
                return -EINVAL;
 
+       rcu_read_lock();
+       if (link_sta_info_hash_lookup(sdata->local, link_sta->addr)) {
+               rcu_read_unlock();
+               return -EALREADY;
+       }
+       /* we only modify under the mutex so this is fine */
+       rcu_read_unlock();
+
        sta->sta.valid_links = new_links;
 
        if (!test_sta_flag(sta, WLAN_STA_INSERTED)) {
@@ -2777,12 +2787,13 @@ int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id)
        if (ret) {
                sta->sta.valid_links = old_links;
                sta_remove_link(sta, link_id, false);
+               return ret;
        }
 
 hash:
-       link_sta_info_hash_add(sdata->local, link_sta);
-
-       return ret;
+       ret = link_sta_info_hash_add(sdata->local, link_sta);
+       WARN_ON(ret);
+       return 0;
 }
 
 void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)