aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Benc <jbenc@suse.cz>2006-06-05 19:39:34 -0400
committerDavid S. Miller <davem@davemloft.net>2006-06-05 19:39:34 -0400
commit36485707bbd9729e0c52315b173aeed9bc2303dd (patch)
tree78997f28e14702d058f90a8ba80a20abcead57d6
parent8c893ff6abbac0c7c05b1cb9bfb6e2dfc4538c75 (diff)
[BRIDGE]: fix locking and memory leak in br_add_bridge
There are several bugs in error handling in br_add_bridge: - when dev_alloc_name fails, allocated net_device is not freed - unregister_netdev is called when rtnl lock is held - free_netdev is called before netdev_run_todo has a chance to be run after unregistering net_device Signed-off-by: Jiri Benc <jbenc@suse.cz> Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/bridge/br_if.c19
1 files changed, 7 insertions, 12 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index ad1c7af65ec8..f5d47bf4f967 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -300,25 +300,20 @@ int br_add_bridge(const char *name)
300 rtnl_lock(); 300 rtnl_lock();
301 if (strchr(dev->name, '%')) { 301 if (strchr(dev->name, '%')) {
302 ret = dev_alloc_name(dev, dev->name); 302 ret = dev_alloc_name(dev, dev->name);
303 if (ret < 0) 303 if (ret < 0) {
304 goto err1; 304 free_netdev(dev);
305 goto out;
306 }
305 } 307 }
306 308
307 ret = register_netdevice(dev); 309 ret = register_netdevice(dev);
308 if (ret) 310 if (ret)
309 goto err2; 311 goto out;
310 312
311 ret = br_sysfs_addbr(dev); 313 ret = br_sysfs_addbr(dev);
312 if (ret) 314 if (ret)
313 goto err3; 315 unregister_netdevice(dev);
314 rtnl_unlock(); 316 out:
315 return 0;
316
317 err3:
318 unregister_netdev(dev);
319 err2:
320 free_netdev(dev);
321 err1:
322 rtnl_unlock(); 317 rtnl_unlock();
323 return ret; 318 return ret;
324} 319}