aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-07-03 06:53:42 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-03 06:53:42 -0400
commitab1b20467cd2214ad89a95d007047cd2a6b5bf5d (patch)
treed6cb28dab25eada6f2963d23afd284d0b899bab5
parent374e7b59498ce0785b3727794b351221528a5159 (diff)
bridge: fix use-after-free in br_cleanup_bridges()
Unregistering a bridge device may cause virtual devices stacked on the bridge, like vlan or macvlan devices, to be unregistered as well. br_cleanup_bridges() uses for_each_netdev_safe() to iterate over all devices during cleanup. This is not enough however, if one of the additionally unregistered devices is next in the list to the bridge device, it will get freed as well and the iteration continues on the freed element. Restart iteration after each bridge device removal from the beginning to fix this, similar to what rtnl_link_unregister() does. Signed-off-by: Patrick McHardy <kaber@trash.net> Acked-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/bridge/br_if.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index c2397f503b0f..f38cc5317b88 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -442,12 +442,16 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
442 442
443void __exit br_cleanup_bridges(void) 443void __exit br_cleanup_bridges(void)
444{ 444{
445 struct net_device *dev, *nxt; 445 struct net_device *dev;
446 446
447 rtnl_lock(); 447 rtnl_lock();
448 for_each_netdev_safe(&init_net, dev, nxt) 448restart:
449 if (dev->priv_flags & IFF_EBRIDGE) 449 for_each_netdev(&init_net, dev) {
450 if (dev->priv_flags & IFF_EBRIDGE) {
450 del_br(dev->priv); 451 del_br(dev->priv);
452 goto restart;
453 }
454 }
451 rtnl_unlock(); 455 rtnl_unlock();
452 456
453} 457}