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>

authored by Neil Horman and committed by David S. Miller 2cc6d2bf bc68580d

+14 -3
+1
include/net/addrconf.h
··· 121 121 * IPv6 Address Label subsystem (addrlabel.c) 122 122 */ 123 123 extern int ipv6_addr_label_init(void); 124 + extern void ipv6_addr_label_cleanup(void); 124 125 extern void ipv6_addr_label_rtnl_register(void); 125 126 extern u32 ipv6_addr_label(struct net *net, 126 127 const struct in6_addr *addr,
+8 -3
net/ipv6/addrconf.c
··· 4637 4637 if (err < 0) { 4638 4638 printk(KERN_CRIT "IPv6 Addrconf:" 4639 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 4647 /* The addrconf netdev notifier requires that loopback_dev 4646 4648 * has it's ipv6 private information allocated and setup ··· 4694 4692 unregister_netdevice_notifier(&ipv6_dev_notf); 4695 4693 errlo: 4696 4694 unregister_pernet_subsys(&addrconf_ops); 4697 - 4695 + out_addrlabel: 4696 + ipv6_addr_label_cleanup(); 4697 + out: 4698 4698 return err; 4699 4699 } 4700 4700 ··· 4707 4703 4708 4704 unregister_netdevice_notifier(&ipv6_dev_notf); 4709 4705 unregister_pernet_subsys(&addrconf_ops); 4706 + ipv6_addr_label_cleanup(); 4710 4707 4711 4708 rtnl_lock(); 4712 4709
+5
net/ipv6/addrlabel.c
··· 393 393 return register_pernet_subsys(&ipv6_addr_label_ops); 394 394 } 395 395 396 + void ipv6_addr_label_cleanup(void) 397 + { 398 + unregister_pernet_subsys(&ipv6_addr_label_ops); 399 + } 400 + 396 401 static const struct nla_policy ifal_policy[IFAL_MAX+1] = { 397 402 [IFAL_ADDRESS] = { .len = sizeof(struct in6_addr), }, 398 403 [IFAL_LABEL] = { .len = sizeof(u32), },