aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2010-10-02 07:17:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-05 13:35:21 -0400
commit85416a4fa193754ef36e12b20bb02fe661cb7f17 (patch)
tree45228e888bd76a5f1251c55ea28377ddedfe2914 /net/mac80211/iface.c
parent5a254ffe3ffdfa84fe076009bd8e88da412180d2 (diff)
mac80211: fix rx monitor filter refcounters
This patch fixes an refcounting bug. Previously it was possible to corrupt the per-device recv. filter and monitor management counters when: iw dev wlanX set monitor [new flags] was issued on an active monitor interface. Acked-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c44
1 files changed, 22 insertions, 22 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 66785739dad3..1300e8859ea7 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -148,6 +148,26 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
148 return 0; 148 return 0;
149} 149}
150 150
151void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
152 const int offset)
153{
154 struct ieee80211_local *local = sdata->local;
155 u32 flags = sdata->u.mntr_flags;
156
157#define ADJUST(_f, _s) do { \
158 if (flags & MONITOR_FLAG_##_f) \
159 local->fif_##_s += offset; \
160 } while (0)
161
162 ADJUST(FCSFAIL, fcsfail);
163 ADJUST(PLCPFAIL, plcpfail);
164 ADJUST(CONTROL, control);
165 ADJUST(CONTROL, pspoll);
166 ADJUST(OTHER_BSS, other_bss);
167
168#undef ADJUST
169}
170
151/* 171/*
152 * NOTE: Be very careful when changing this function, it must NOT return 172 * NOTE: Be very careful when changing this function, it must NOT return
153 * an error on interface type changes that have been pre-checked, so most 173 * an error on interface type changes that have been pre-checked, so most
@@ -240,17 +260,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
240 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; 260 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
241 } 261 }
242 262
243 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 263 ieee80211_adjust_monitor_flags(sdata, 1);
244 local->fif_fcsfail++;
245 if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
246 local->fif_plcpfail++;
247 if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
248 local->fif_control++;
249 local->fif_pspoll++;
250 }
251 if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
252 local->fif_other_bss++;
253
254 ieee80211_configure_filter(local); 264 ieee80211_configure_filter(local);
255 265
256 netif_carrier_on(dev); 266 netif_carrier_on(dev);
@@ -477,17 +487,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
477 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; 487 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
478 } 488 }
479 489
480 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 490 ieee80211_adjust_monitor_flags(sdata, -1);
481 local->fif_fcsfail--;
482 if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
483 local->fif_plcpfail--;
484 if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) {
485 local->fif_pspoll--;
486 local->fif_control--;
487 }
488 if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
489 local->fif_other_bss--;
490
491 ieee80211_configure_filter(local); 491 ieee80211_configure_filter(local);
492 break; 492 break;
493 case NL80211_IFTYPE_MESH_POINT: 493 case NL80211_IFTYPE_MESH_POINT: