Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cc6d2bf authored by Neil Horman's avatar Neil Horman Committed by David S. Miller
Browse files

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: default avatarNeil 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: default avatarDavid S. Miller <davem@davemloft.net>
parent bc68580d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ static inline int addrconf_finite_timeout(unsigned long timeout)
 *	IPv6 Address Label subsystem (addrlabel.c)
 */
extern int			ipv6_addr_label_init(void);
extern void			ipv6_addr_label_cleanup(void);
extern void			ipv6_addr_label_rtnl_register(void);
extern u32			ipv6_addr_label(struct net *net,
						const struct in6_addr *addr,
+8 −3
Original line number Diff line number Diff line
@@ -4637,10 +4637,12 @@ int __init addrconf_init(void)
	if (err < 0) {
		printk(KERN_CRIT "IPv6 Addrconf:"
		       " cannot initialize default policy table: %d.\n", err);
		return err;
		goto out;
	}

	register_pernet_subsys(&addrconf_ops);
	err = register_pernet_subsys(&addrconf_ops);
	if (err < 0)
		goto out_addrlabel;

	/* The addrconf netdev notifier requires that loopback_dev
	 * has it's ipv6 private information allocated and setup
@@ -4692,7 +4694,9 @@ errout:
	unregister_netdevice_notifier(&ipv6_dev_notf);
errlo:
	unregister_pernet_subsys(&addrconf_ops);

out_addrlabel:
	ipv6_addr_label_cleanup();
out:
	return err;
}

@@ -4703,6 +4707,7 @@ void addrconf_cleanup(void)

	unregister_netdevice_notifier(&ipv6_dev_notf);
	unregister_pernet_subsys(&addrconf_ops);
	ipv6_addr_label_cleanup();

	rtnl_lock();

+5 −0
Original line number Diff line number Diff line
@@ -393,6 +393,11 @@ int __init ipv6_addr_label_init(void)
	return register_pernet_subsys(&ipv6_addr_label_ops);
}

void ipv6_addr_label_cleanup(void)
{
	unregister_pernet_subsys(&ipv6_addr_label_ops);
}

static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
	[IFAL_ADDRESS]		= { .len = sizeof(struct in6_addr), },
	[IFAL_LABEL]		= { .len = sizeof(u32), },