aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-03 09:41:13 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-11-09 16:01:02 -0500
commit7b7eab6fc1bc8852d9649541b59283cd89cc526f (patch)
tree7b071ee01187bc3ee843c86b88189cc4eab73cf1 /net
parent6e3e939f3b1bf8534b32ad09ff199d88800835a0 (diff)
mac80211: verify virtual interfaces in driver API
The driver is never informed about monitor or AP_VLAN interfaces, so whenever we pass those to it later this is a bug. Verify we don't as there are some cases where this could happen. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/driver-ops.h68
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c6
-rw-r--r--net/mac80211/pm.c2
-rw-r--r--net/mac80211/util.c2
5 files changed, 69 insertions, 11 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 5f165d7eb2d..b12ed52732c 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -5,6 +5,11 @@
5#include "ieee80211_i.h" 5#include "ieee80211_i.h"
6#include "driver-trace.h" 6#include "driver-trace.h"
7 7
8static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
9{
10 WARN_ON(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER));
11}
12
8static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) 13static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
9{ 14{
10 local->ops->tx(&local->hw, skb); 15 local->ops->tx(&local->hw, skb);
@@ -69,15 +74,23 @@ static inline int drv_resume(struct ieee80211_local *local)
69#endif 74#endif
70 75
71static inline int drv_add_interface(struct ieee80211_local *local, 76static inline int drv_add_interface(struct ieee80211_local *local,
72 struct ieee80211_vif *vif) 77 struct ieee80211_sub_if_data *sdata)
73{ 78{
74 int ret; 79 int ret;
75 80
76 might_sleep(); 81 might_sleep();
77 82
78 trace_drv_add_interface(local, vif_to_sdata(vif)); 83 if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
79 ret = local->ops->add_interface(&local->hw, vif); 84 sdata->vif.type == NL80211_IFTYPE_MONITOR))
85 return -EINVAL;
86
87 trace_drv_add_interface(local, sdata);
88 ret = local->ops->add_interface(&local->hw, &sdata->vif);
80 trace_drv_return_int(local, ret); 89 trace_drv_return_int(local, ret);
90
91 if (ret == 0)
92 sdata->flags |= IEEE80211_SDATA_IN_DRIVER;
93
81 return ret; 94 return ret;
82} 95}
83 96
@@ -89,6 +102,8 @@ static inline int drv_change_interface(struct ieee80211_local *local,
89 102
90 might_sleep(); 103 might_sleep();
91 104
105 check_sdata_in_driver(sdata);
106
92 trace_drv_change_interface(local, sdata, type, p2p); 107 trace_drv_change_interface(local, sdata, type, p2p);
93 ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); 108 ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
94 trace_drv_return_int(local, ret); 109 trace_drv_return_int(local, ret);
@@ -96,12 +111,15 @@ static inline int drv_change_interface(struct ieee80211_local *local,
96} 111}
97 112
98static inline void drv_remove_interface(struct ieee80211_local *local, 113static inline void drv_remove_interface(struct ieee80211_local *local,
99 struct ieee80211_vif *vif) 114 struct ieee80211_sub_if_data *sdata)
100{ 115{
101 might_sleep(); 116 might_sleep();
102 117
103 trace_drv_remove_interface(local, vif_to_sdata(vif)); 118 check_sdata_in_driver(sdata);
104 local->ops->remove_interface(&local->hw, vif); 119
120 trace_drv_remove_interface(local, sdata);
121 local->ops->remove_interface(&local->hw, &sdata->vif);
122 sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
105 trace_drv_return_void(local); 123 trace_drv_return_void(local);
106} 124}
107 125
@@ -124,6 +142,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
124{ 142{
125 might_sleep(); 143 might_sleep();
126 144
145 check_sdata_in_driver(sdata);
146
127 trace_drv_bss_info_changed(local, sdata, info, changed); 147 trace_drv_bss_info_changed(local, sdata, info, changed);
128 if (local->ops->bss_info_changed) 148 if (local->ops->bss_info_changed)
129 local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); 149 local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
@@ -139,6 +159,8 @@ static inline int drv_tx_sync(struct ieee80211_local *local,
139 159
140 might_sleep(); 160 might_sleep();
141 161
162 check_sdata_in_driver(sdata);
163
142 trace_drv_tx_sync(local, sdata, bssid, type); 164 trace_drv_tx_sync(local, sdata, bssid, type);
143 if (local->ops->tx_sync) 165 if (local->ops->tx_sync)
144 ret = local->ops->tx_sync(&local->hw, &sdata->vif, 166 ret = local->ops->tx_sync(&local->hw, &sdata->vif,
@@ -154,6 +176,8 @@ static inline void drv_finish_tx_sync(struct ieee80211_local *local,
154{ 176{
155 might_sleep(); 177 might_sleep();
156 178
179 check_sdata_in_driver(sdata);
180
157 trace_drv_finish_tx_sync(local, sdata, bssid, type); 181 trace_drv_finish_tx_sync(local, sdata, bssid, type);
158 if (local->ops->finish_tx_sync) 182 if (local->ops->finish_tx_sync)
159 local->ops->finish_tx_sync(&local->hw, &sdata->vif, 183 local->ops->finish_tx_sync(&local->hw, &sdata->vif,
@@ -211,6 +235,8 @@ static inline int drv_set_key(struct ieee80211_local *local,
211 235
212 might_sleep(); 236 might_sleep();
213 237
238 check_sdata_in_driver(sdata);
239
214 trace_drv_set_key(local, cmd, sdata, sta, key); 240 trace_drv_set_key(local, cmd, sdata, sta, key);
215 ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); 241 ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
216 trace_drv_return_int(local, ret); 242 trace_drv_return_int(local, ret);
@@ -228,6 +254,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local,
228 if (sta) 254 if (sta)
229 ista = &sta->sta; 255 ista = &sta->sta;
230 256
257 check_sdata_in_driver(sdata);
258
231 trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); 259 trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
232 if (local->ops->update_tkip_key) 260 if (local->ops->update_tkip_key)
233 local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, 261 local->ops->update_tkip_key(&local->hw, &sdata->vif, conf,
@@ -243,6 +271,8 @@ static inline int drv_hw_scan(struct ieee80211_local *local,
243 271
244 might_sleep(); 272 might_sleep();
245 273
274 check_sdata_in_driver(sdata);
275
246 trace_drv_hw_scan(local, sdata); 276 trace_drv_hw_scan(local, sdata);
247 ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); 277 ret = local->ops->hw_scan(&local->hw, &sdata->vif, req);
248 trace_drv_return_int(local, ret); 278 trace_drv_return_int(local, ret);
@@ -254,6 +284,8 @@ static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
254{ 284{
255 might_sleep(); 285 might_sleep();
256 286
287 check_sdata_in_driver(sdata);
288
257 trace_drv_cancel_hw_scan(local, sdata); 289 trace_drv_cancel_hw_scan(local, sdata);
258 local->ops->cancel_hw_scan(&local->hw, &sdata->vif); 290 local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
259 trace_drv_return_void(local); 291 trace_drv_return_void(local);
@@ -269,6 +301,8 @@ drv_sched_scan_start(struct ieee80211_local *local,
269 301
270 might_sleep(); 302 might_sleep();
271 303
304 check_sdata_in_driver(sdata);
305
272 trace_drv_sched_scan_start(local, sdata); 306 trace_drv_sched_scan_start(local, sdata);
273 ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, 307 ret = local->ops->sched_scan_start(&local->hw, &sdata->vif,
274 req, ies); 308 req, ies);
@@ -281,6 +315,8 @@ static inline void drv_sched_scan_stop(struct ieee80211_local *local,
281{ 315{
282 might_sleep(); 316 might_sleep();
283 317
318 check_sdata_in_driver(sdata);
319
284 trace_drv_sched_scan_stop(local, sdata); 320 trace_drv_sched_scan_stop(local, sdata);
285 local->ops->sched_scan_stop(&local->hw, &sdata->vif); 321 local->ops->sched_scan_stop(&local->hw, &sdata->vif);
286 trace_drv_return_void(local); 322 trace_drv_return_void(local);
@@ -377,6 +413,8 @@ static inline void drv_sta_notify(struct ieee80211_local *local,
377 enum sta_notify_cmd cmd, 413 enum sta_notify_cmd cmd,
378 struct ieee80211_sta *sta) 414 struct ieee80211_sta *sta)
379{ 415{
416 check_sdata_in_driver(sdata);
417
380 trace_drv_sta_notify(local, sdata, cmd, sta); 418 trace_drv_sta_notify(local, sdata, cmd, sta);
381 if (local->ops->sta_notify) 419 if (local->ops->sta_notify)
382 local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); 420 local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta);
@@ -391,6 +429,8 @@ static inline int drv_sta_add(struct ieee80211_local *local,
391 429
392 might_sleep(); 430 might_sleep();
393 431
432 check_sdata_in_driver(sdata);
433
394 trace_drv_sta_add(local, sdata, sta); 434 trace_drv_sta_add(local, sdata, sta);
395 if (local->ops->sta_add) 435 if (local->ops->sta_add)
396 ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); 436 ret = local->ops->sta_add(&local->hw, &sdata->vif, sta);
@@ -406,6 +446,8 @@ static inline void drv_sta_remove(struct ieee80211_local *local,
406{ 446{
407 might_sleep(); 447 might_sleep();
408 448
449 check_sdata_in_driver(sdata);
450
409 trace_drv_sta_remove(local, sdata, sta); 451 trace_drv_sta_remove(local, sdata, sta);
410 if (local->ops->sta_remove) 452 if (local->ops->sta_remove)
411 local->ops->sta_remove(&local->hw, &sdata->vif, sta); 453 local->ops->sta_remove(&local->hw, &sdata->vif, sta);
@@ -421,6 +463,8 @@ static inline int drv_conf_tx(struct ieee80211_local *local,
421 463
422 might_sleep(); 464 might_sleep();
423 465
466 check_sdata_in_driver(sdata);
467
424 trace_drv_conf_tx(local, sdata, queue, params); 468 trace_drv_conf_tx(local, sdata, queue, params);
425 if (local->ops->conf_tx) 469 if (local->ops->conf_tx)
426 ret = local->ops->conf_tx(&local->hw, &sdata->vif, 470 ret = local->ops->conf_tx(&local->hw, &sdata->vif,
@@ -436,6 +480,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local,
436 480
437 might_sleep(); 481 might_sleep();
438 482
483 check_sdata_in_driver(sdata);
484
439 trace_drv_get_tsf(local, sdata); 485 trace_drv_get_tsf(local, sdata);
440 if (local->ops->get_tsf) 486 if (local->ops->get_tsf)
441 ret = local->ops->get_tsf(&local->hw, &sdata->vif); 487 ret = local->ops->get_tsf(&local->hw, &sdata->vif);
@@ -449,6 +495,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local,
449{ 495{
450 might_sleep(); 496 might_sleep();
451 497
498 check_sdata_in_driver(sdata);
499
452 trace_drv_set_tsf(local, sdata, tsf); 500 trace_drv_set_tsf(local, sdata, tsf);
453 if (local->ops->set_tsf) 501 if (local->ops->set_tsf)
454 local->ops->set_tsf(&local->hw, &sdata->vif, tsf); 502 local->ops->set_tsf(&local->hw, &sdata->vif, tsf);
@@ -460,6 +508,8 @@ static inline void drv_reset_tsf(struct ieee80211_local *local,
460{ 508{
461 might_sleep(); 509 might_sleep();
462 510
511 check_sdata_in_driver(sdata);
512
463 trace_drv_reset_tsf(local, sdata); 513 trace_drv_reset_tsf(local, sdata);
464 if (local->ops->reset_tsf) 514 if (local->ops->reset_tsf)
465 local->ops->reset_tsf(&local->hw, &sdata->vif); 515 local->ops->reset_tsf(&local->hw, &sdata->vif);
@@ -489,6 +539,8 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
489 539
490 might_sleep(); 540 might_sleep();
491 541
542 check_sdata_in_driver(sdata);
543
492 trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); 544 trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
493 545
494 if (local->ops->ampdu_action) 546 if (local->ops->ampdu_action)
@@ -644,6 +696,8 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local,
644 696
645 might_sleep(); 697 might_sleep();
646 698
699 check_sdata_in_driver(sdata);
700
647 trace_drv_set_bitrate_mask(local, sdata, mask); 701 trace_drv_set_bitrate_mask(local, sdata, mask);
648 if (local->ops->set_bitrate_mask) 702 if (local->ops->set_bitrate_mask)
649 ret = local->ops->set_bitrate_mask(&local->hw, 703 ret = local->ops->set_bitrate_mask(&local->hw,
@@ -657,6 +711,8 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local,
657 struct ieee80211_sub_if_data *sdata, 711 struct ieee80211_sub_if_data *sdata,
658 struct cfg80211_gtk_rekey_data *data) 712 struct cfg80211_gtk_rekey_data *data)
659{ 713{
714 check_sdata_in_driver(sdata);
715
660 trace_drv_set_rekey_data(local, sdata, data); 716 trace_drv_set_rekey_data(local, sdata, data);
661 if (local->ops->set_rekey_data) 717 if (local->ops->set_rekey_data)
662 local->ops->set_rekey_data(&local->hw, &sdata->vif, data); 718 local->ops->set_rekey_data(&local->hw, &sdata->vif, data);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e2447096c94..386330c89ba 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -543,6 +543,7 @@ struct ieee80211_if_mesh {
543 * associated stations and deliver multicast frames both 543 * associated stations and deliver multicast frames both
544 * back to wireless media and to the local net stack. 544 * back to wireless media and to the local net stack.
545 * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume. 545 * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume.
546 * @IEEE80211_SDATA_IN_DRIVER: indicates interface was added to driver
546 */ 547 */
547enum ieee80211_sub_if_data_flags { 548enum ieee80211_sub_if_data_flags {
548 IEEE80211_SDATA_ALLMULTI = BIT(0), 549 IEEE80211_SDATA_ALLMULTI = BIT(0),
@@ -550,6 +551,7 @@ enum ieee80211_sub_if_data_flags {
550 IEEE80211_SDATA_OPERATING_GMODE = BIT(2), 551 IEEE80211_SDATA_OPERATING_GMODE = BIT(2),
551 IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), 552 IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3),
552 IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4), 553 IEEE80211_SDATA_DISCONNECT_RESUME = BIT(4),
554 IEEE80211_SDATA_IN_DRIVER = BIT(5),
553}; 555};
554 556
555/** 557/**
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 33a974663f7..4ee624c543c 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -265,7 +265,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
265 break; 265 break;
266 default: 266 default:
267 if (coming_up) { 267 if (coming_up) {
268 res = drv_add_interface(local, &sdata->vif); 268 res = drv_add_interface(local, sdata);
269 if (res) 269 if (res)
270 goto err_stop; 270 goto err_stop;
271 } 271 }
@@ -345,7 +345,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
345 345
346 return 0; 346 return 0;
347 err_del_interface: 347 err_del_interface:
348 drv_remove_interface(local, &sdata->vif); 348 drv_remove_interface(local, sdata);
349 err_stop: 349 err_stop:
350 if (!local->open_count) 350 if (!local->open_count)
351 drv_stop(local); 351 drv_stop(local);
@@ -520,7 +520,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
520 ieee80211_free_keys(sdata); 520 ieee80211_free_keys(sdata);
521 521
522 if (going_down) 522 if (going_down)
523 drv_remove_interface(local, &sdata->vif); 523 drv_remove_interface(local, sdata);
524 } 524 }
525 525
526 sdata->bss = NULL; 526 sdata->bss = NULL;
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 9ee7164b207..596efaf50e0 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -125,7 +125,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
125 ieee80211_bss_info_change_notify(sdata, 125 ieee80211_bss_info_change_notify(sdata,
126 BSS_CHANGED_BEACON_ENABLED); 126 BSS_CHANGED_BEACON_ENABLED);
127 127
128 drv_remove_interface(local, &sdata->vif); 128 drv_remove_interface(local, sdata);
129 } 129 }
130 130
131 /* stop hardware - this must stop RX */ 131 /* stop hardware - this must stop RX */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 83c482177ec..98ca5479324 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1006,7 +1006,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1006 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 1006 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
1007 sdata->vif.type != NL80211_IFTYPE_MONITOR && 1007 sdata->vif.type != NL80211_IFTYPE_MONITOR &&
1008 ieee80211_sdata_running(sdata)) 1008 ieee80211_sdata_running(sdata))
1009 res = drv_add_interface(local, &sdata->vif); 1009 res = drv_add_interface(local, sdata);
1010 } 1010 }
1011 1011
1012 /* add STAs back */ 1012 /* add STAs back */