]> err.no Git - linux-2.6/commitdiff
bridge: fix use-after-free in br_cleanup_bridges()
authorPatrick McHardy <kaber@trash.net>
Thu, 3 Jul 2008 10:53:42 +0000 (03:53 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 3 Jul 2008 10:53:42 +0000 (03:53 -0700)
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>
net/bridge/br_if.c

index c2397f503b0f94e850d7da40b68e53fb16b9f9ae..f38cc5317b888bd45f271ed7db5a0f065ada9803 100644 (file)
@@ -442,12 +442,16 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
 
 void __exit br_cleanup_bridges(void)
 {
-       struct net_device *dev, *nxt;
+       struct net_device *dev;
 
        rtnl_lock();
-       for_each_netdev_safe(&init_net, dev, nxt)
-               if (dev->priv_flags & IFF_EBRIDGE)
+restart:
+       for_each_netdev(&init_net, dev) {
+               if (dev->priv_flags & IFF_EBRIDGE) {
                        del_br(dev->priv);
+                       goto restart;
+               }
+       }
        rtnl_unlock();
 
 }