From 0ad49045f28474b3cbc1f27ec7a4238970734764 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 18 Jul 2022 22:54:27 +0200 Subject: [PATCH] wifi: mac80211: fix link sta hash table handling There are two issues here: we unhash the link stations only directly before freeing the station they belong to, and we also don't unhash all the links correctly in all cases. Fix these issues. Fixes: ba6ddab94fc6 ("wifi: mac80211: maintain link-sta hash table") Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 75122ece..44e21de 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -358,7 +358,7 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) if (!(sta->sta.valid_links & BIT(i))) continue; - sta_remove_link(sta, i, true); + sta_remove_link(sta, i, false); } /* @@ -846,6 +846,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) return 0; out_remove: + if (sta->sta.valid_links) + link_sta_info_hash_del(local, &sta->deflink); sta_info_hash_del(local, sta); list_del_rcu(&sta->list); out_drop_sta: @@ -1140,7 +1142,7 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta) { struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; - int ret; + int ret, i; might_sleep(); @@ -1168,6 +1170,18 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta) */ drv_sync_rx_queues(local, sta); + for (i = 0; i < ARRAY_SIZE(sta->link); i++) { + struct link_sta_info *link_sta; + + if (!(sta->sta.valid_links & BIT(i))) + continue; + + link_sta = rcu_dereference_protected(sta->link[i], + lockdep_is_held(&local->sta_mtx)); + + link_sta_info_hash_del(local, link_sta); + } + ret = sta_info_hash_del(local, sta); if (WARN_ON(ret)) return ret; -- 2.7.4