diff options
author | Neil Horman <nhorman@tuxdriver.com> | 2010-09-24 05:55:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-26 22:09:25 -0400 |
commit | 2cc6d2bf3d6195fabcf0febc192c01f99519a8f3 (patch) | |
tree | 6fbbaa255617783eda308a00a21065bc99ad0d21 /net/ipv6/addrconf.c | |
parent | bc68580d41b131396054a1a04a7df4948555ed97 (diff) |
ipv6: add a missing unregister_pernet_subsys call
Clean up a missing exit path in the ipv6 module init routines. In
addrconf_init we call ipv6_addr_label_init which calls register_pernet_subsys
for the ipv6_addr_label_ops structure. But if module loading fails, or if the
ipv6 module is removed, there is no corresponding unregister_pernet_subsys call,
which leaves a now-bogus address on the pernet_list, leading to oopses in
subsequent registrations. This patch cleans up both the failed load path and
the unload path. Tested by myself with good results.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
include/net/addrconf.h | 1 +
net/ipv6/addrconf.c | 11 ++++++++---
net/ipv6/addrlabel.c | 5 +++++
3 files changed, 14 insertions(+), 3 deletions(-)
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ab70a3fbcafa..324fac3b6c16 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -4637,10 +4637,12 @@ int __init addrconf_init(void) | |||
4637 | if (err < 0) { | 4637 | if (err < 0) { |
4638 | printk(KERN_CRIT "IPv6 Addrconf:" | 4638 | printk(KERN_CRIT "IPv6 Addrconf:" |
4639 | " cannot initialize default policy table: %d.\n", err); | 4639 | " cannot initialize default policy table: %d.\n", err); |
4640 | return err; | 4640 | goto out; |
4641 | } | 4641 | } |
4642 | 4642 | ||
4643 | register_pernet_subsys(&addrconf_ops); | 4643 | err = register_pernet_subsys(&addrconf_ops); |
4644 | if (err < 0) | ||
4645 | goto out_addrlabel; | ||
4644 | 4646 | ||
4645 | /* The addrconf netdev notifier requires that loopback_dev | 4647 | /* The addrconf netdev notifier requires that loopback_dev |
4646 | * has it's ipv6 private information allocated and setup | 4648 | * has it's ipv6 private information allocated and setup |
@@ -4692,7 +4694,9 @@ errout: | |||
4692 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4694 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4693 | errlo: | 4695 | errlo: |
4694 | unregister_pernet_subsys(&addrconf_ops); | 4696 | unregister_pernet_subsys(&addrconf_ops); |
4695 | 4697 | out_addrlabel: | |
4698 | ipv6_addr_label_cleanup(); | ||
4699 | out: | ||
4696 | return err; | 4700 | return err; |
4697 | } | 4701 | } |
4698 | 4702 | ||
@@ -4703,6 +4707,7 @@ void addrconf_cleanup(void) | |||
4703 | 4707 | ||
4704 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4708 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4705 | unregister_pernet_subsys(&addrconf_ops); | 4709 | unregister_pernet_subsys(&addrconf_ops); |
4710 | ipv6_addr_label_cleanup(); | ||
4706 | 4711 | ||
4707 | rtnl_lock(); | 4712 | rtnl_lock(); |
4708 | 4713 | ||