aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-12-04 14:11:06 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-12-16 05:29:45 -0500
commita710c8160dd93e981163759aad754f758850273a (patch)
tree1b125791f1a332af6a219bca9072bd7085d28f92 /net/mac80211/sta_info.c
parent1ddbbb0c83de82599b1baf14bf6bb69a774d4fc7 (diff)
mac80211: move 4-addr sta pointer clearing before synchronize_rcu()
The pointer should be cleared before synchronize_rcu() so that the consequently dead station won't be found by any lookups in the TX or RX paths. Also check that the station is actually the one being removed, the check is not needed because each 4-addr VLAN can only have a single station and non-4-addr VLANs always have a NULL pointer there, but the code is clearer this way (and we avoid the memory write.) Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 1e147742eccf..557ac250ac10 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -875,6 +875,10 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
875 875
876 drv_sta_pre_rcu_remove(local, sta->sdata, sta); 876 drv_sta_pre_rcu_remove(local, sta->sdata, sta);
877 877
878 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
879 rcu_access_pointer(sdata->u.vlan.sta) == sta)
880 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
881
878 /* this always calls synchronize_net() */ 882 /* this always calls synchronize_net() */
879 ieee80211_free_sta_keys(local, sta); 883 ieee80211_free_sta_keys(local, sta);
880 884
@@ -883,9 +887,6 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
883 local->num_sta--; 887 local->num_sta--;
884 local->sta_generation++; 888 local->sta_generation++;
885 889
886 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
887 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
888
889 while (sta->sta_state > IEEE80211_STA_NONE) { 890 while (sta->sta_state > IEEE80211_STA_NONE) {
890 ret = sta_info_move_state(sta, sta->sta_state - 1); 891 ret = sta_info_move_state(sta, sta->sta_state - 1);
891 if (ret) { 892 if (ret) {