aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-04-01 09:21:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-01 17:14:10 -0400
commit93e5deb1ae39b56f4743955e76c72251256f23c1 (patch)
tree415d4f11449452822bdd1a97760de67ffd8c452d /net/mac80211/sta_info.c
parent97bff8ecf4e4e26749a67dcfbb7565d8a0f4acb4 (diff)
mac80211: automatically free sta struct when insertion fails
When STA structure insertion fails, it has been allocated but isn't really alive yet, it isn't reachable by any other code and also can't yet have much configured. This patch changes the code so that when the insertion fails, the resulting STA pointer is no longer valid because it is freed. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.c')
-rw-r--r--net/mac80211/sta_info.c80
1 files changed, 57 insertions, 23 deletions
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 2a5a2f067bae..5497ca1843fe 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -36,16 +36,23 @@
36 * (which is pretty useless) or insert it into the hash table using 36 * (which is pretty useless) or insert it into the hash table using
37 * sta_info_insert() which demotes the reference from ownership to a regular 37 * sta_info_insert() which demotes the reference from ownership to a regular
38 * RCU-protected reference; if the function is called without protection by an 38 * RCU-protected reference; if the function is called without protection by an
39 * RCU critical section the reference is instantly invalidated. 39 * RCU critical section the reference is instantly invalidated. Note that the
40 * caller may not do much with the STA info before inserting it, in particular,
41 * it may not start any mesh peer link management or add encryption keys.
42 *
43 * When the insertion fails (sta_info_insert()) returns non-zero), the
44 * structure will have been freed by sta_info_insert()!
40 * 45 *
41 * Because there are debugfs entries for each station, and adding those 46 * Because there are debugfs entries for each station, and adding those
42 * must be able to sleep, it is also possible to "pin" a station entry, 47 * must be able to sleep, it is also possible to "pin" a station entry,
43 * that means it can be removed from the hash table but not be freed. 48 * that means it can be removed from the hash table but not be freed.
44 * See the comment in __sta_info_unlink() for more information. 49 * See the comment in __sta_info_unlink() for more information, this is
50 * an internal capability only.
45 * 51 *
46 * In order to remove a STA info structure, the caller needs to first 52 * In order to remove a STA info structure, the caller needs to first
47 * unlink it (sta_info_unlink()) from the list and hash tables and 53 * unlink it (sta_info_unlink()) from the list and hash tables and
48 * then wait for an RCU synchronisation before it can be freed. Due to 54 * then destroy it while holding the RTNL; sta_info_destroy() will wait
55 * for an RCU grace period to elapse before actually freeing it. Due to
49 * the pinning and the possibility of multiple callers trying to remove 56 * the pinning and the possibility of multiple callers trying to remove
50 * the same STA info at the same time, sta_info_unlink() can clear the 57 * the same STA info at the same time, sta_info_unlink() can clear the
51 * STA info pointer it is passed to indicate that the STA info is owned 58 * STA info pointer it is passed to indicate that the STA info is owned
@@ -127,12 +134,35 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
127 return NULL; 134 return NULL;
128} 135}
129 136
137/**
138 * __sta_info_free - internal STA free helper
139 *
140 * @sta: STA info to free
141 *
142 * This function must undo everything done by sta_info_alloc()
143 * that may happen before sta_info_insert().
144 */
145static void __sta_info_free(struct ieee80211_local *local,
146 struct sta_info *sta)
147{
148 DECLARE_MAC_BUF(mbuf);
149
150 rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
151 rate_control_put(sta->rate_ctrl);
152
153#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
154 printk(KERN_DEBUG "%s: Destroyed STA %s\n",
155 wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
156#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
157
158 kfree(sta);
159}
160
130void sta_info_destroy(struct sta_info *sta) 161void sta_info_destroy(struct sta_info *sta)
131{ 162{
132 struct ieee80211_local *local; 163 struct ieee80211_local *local;
133 struct sk_buff *skb; 164 struct sk_buff *skb;
134 int i; 165 int i;
135 DECLARE_MAC_BUF(mbuf);
136 166
137 ASSERT_RTNL(); 167 ASSERT_RTNL();
138 might_sleep(); 168 might_sleep();
@@ -182,15 +212,7 @@ void sta_info_destroy(struct sta_info *sta)
182 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 212 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
183 } 213 }
184 214
185 rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); 215 __sta_info_free(local, sta);
186 rate_control_put(sta->rate_ctrl);
187
188#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
189 printk(KERN_DEBUG "%s: Destroyed STA %s\n",
190 wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
191#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
192
193 kfree(sta);
194} 216}
195 217
196 218
@@ -266,6 +288,7 @@ int sta_info_insert(struct sta_info *sta)
266 struct ieee80211_local *local = sta->local; 288 struct ieee80211_local *local = sta->local;
267 struct ieee80211_sub_if_data *sdata = sta->sdata; 289 struct ieee80211_sub_if_data *sdata = sta->sdata;
268 unsigned long flags; 290 unsigned long flags;
291 int err = 0;
269 DECLARE_MAC_BUF(mac); 292 DECLARE_MAC_BUF(mac);
270 293
271 /* 294 /*
@@ -273,20 +296,23 @@ int sta_info_insert(struct sta_info *sta)
273 * something inserts a STA (on one CPU) without holding the RTNL 296 * something inserts a STA (on one CPU) without holding the RTNL
274 * and another CPU turns off the net device. 297 * and another CPU turns off the net device.
275 */ 298 */
276 if (unlikely(!netif_running(sdata->dev))) 299 if (unlikely(!netif_running(sdata->dev))) {
277 return -ENETDOWN; 300 err = -ENETDOWN;
278 301 goto out_free;
279 if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0)) 302 }
280 return -EINVAL;
281 303
282 if (WARN_ON(is_multicast_ether_addr(sta->addr))) 304 if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 ||
283 return -EINVAL; 305 is_multicast_ether_addr(sta->addr))) {
306 err = -EINVAL;
307 goto out_free;
308 }
284 309
285 spin_lock_irqsave(&local->sta_lock, flags); 310 spin_lock_irqsave(&local->sta_lock, flags);
286 /* check if STA exists already */ 311 /* check if STA exists already */
287 if (__sta_info_find(local, sta->addr)) { 312 if (__sta_info_find(local, sta->addr)) {
288 spin_unlock_irqrestore(&local->sta_lock, flags); 313 spin_unlock_irqrestore(&local->sta_lock, flags);
289 return -EEXIST; 314 err = -EEXIST;
315 goto out_free;
290 } 316 }
291 list_add(&sta->list, &local->sta_list); 317 list_add(&sta->list, &local->sta_list);
292 local->num_sta++; 318 local->num_sta++;
@@ -309,9 +335,13 @@ int sta_info_insert(struct sta_info *sta)
309 spin_unlock_irqrestore(&local->sta_lock, flags); 335 spin_unlock_irqrestore(&local->sta_lock, flags);
310 336
311#ifdef CONFIG_MAC80211_DEBUGFS 337#ifdef CONFIG_MAC80211_DEBUGFS
312 /* debugfs entry adding might sleep, so schedule process 338 /*
339 * Debugfs entry adding might sleep, so schedule process
313 * context task for adding entry for STAs that do not yet 340 * context task for adding entry for STAs that do not yet
314 * have one. */ 341 * have one.
342 * NOTE: due to auto-freeing semantics this may only be done
343 * if the insertion is successful!
344 */
315 queue_work(local->hw.workqueue, &local->sta_debugfs_add); 345 queue_work(local->hw.workqueue, &local->sta_debugfs_add);
316#endif 346#endif
317 347
@@ -319,6 +349,10 @@ int sta_info_insert(struct sta_info *sta)
319 mesh_accept_plinks_update(sdata); 349 mesh_accept_plinks_update(sdata);
320 350
321 return 0; 351 return 0;
352 out_free:
353 BUG_ON(!err);
354 __sta_info_free(local, sta);
355 return err;
322} 356}
323 357
324static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) 358static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)