aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-05-23 19:06:09 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-05-27 05:26:47 -0400
commitc8aa22db0112f640ac6631347f850879c621840b (patch)
treeb6865c7260beecedfeca2ce88a2d32005404d649
parent1351c5d3b189a487fbacd5cdf2dc3e6faf12c682 (diff)
mac80211: close AP_VLAN interfaces before unregistering all
Since Eric's commit efe117ab8 ("Speedup ieee80211_remove_interfaces") there's a bug in mac80211 when it unregisters with AP_VLAN interfaces up. If the AP_VLAN interface was registered after the AP it belongs to (which is the typical case) and then we get into this code path, unregister_netdevice_many() will crash because it isn't prepared to deal with interfaces being closed in the middle of it. Exactly this happens though, because we iterate the list, find the AP master this AP_VLAN belongs to and dev_close() the dependent VLANs. After this, unregister_netdevice_many() won't pick up the fact that the AP_VLAN is already down and will do it again, causing a crash. Cc: stable@vger.kernel.org [2.6.33+] Cc: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/iface.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 00e2238355f0..ceef64426a8d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1703,6 +1703,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
1703 1703
1704 ASSERT_RTNL(); 1704 ASSERT_RTNL();
1705 1705
1706 /*
1707 * Close all AP_VLAN interfaces first, as otherwise they
1708 * might be closed while the AP interface they belong to
1709 * is closed, causing unregister_netdevice_many() to crash.
1710 */
1711 list_for_each_entry(sdata, &local->interfaces, list)
1712 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1713 dev_close(sdata->dev);
1714
1706 mutex_lock(&local->iflist_mtx); 1715 mutex_lock(&local->iflist_mtx);
1707 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { 1716 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
1708 list_del(&sdata->list); 1717 list_del(&sdata->list);