diff options
| author | Jiri Benc <jbenc@suse.cz> | 2006-06-05 19:39:34 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2006-06-05 19:39:34 -0400 |
| commit | 36485707bbd9729e0c52315b173aeed9bc2303dd (patch) | |
| tree | 78997f28e14702d058f90a8ba80a20abcead57d6 | |
| parent | 8c893ff6abbac0c7c05b1cb9bfb6e2dfc4538c75 (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.c | 19 |
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 | } |
