lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20140317161853.2e880469@nehalam.linuxnetplumber.net>
Date:	Mon, 17 Mar 2014 16:18:53 -0700
From:	Stephen Hemminger <stephen@...workplumber.org>
To:	David Miller <davem@...emloft.net>,
	Hannes Frederic Sowa <hannes@...essinduktion.org>
Cc:	netdev@...r.kernel.org
Subject: [PATCH net] ipv6: fix RTNL assert fail in DAD

IPv6 duplicate address detection is triggering the following assertion
failure when using macvlan + vif + multicast.
 RTNL: assertion failed at net/core/dev.c (4496)

This happens because the DAD timer is adding a multicast address without
acquiring the RTNL mutex. In order to acquire the RTNL mutex, it must be
done in process context; therefore it must be in a workqueue.

Full backtrace:
[  541.030090] RTNL: assertion failed at net/core/dev.c (4496)
[  541.031143] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G           O 3.10.33-1-amd64-vyatta #1
[  541.031145] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
[  541.031146]  ffffffff8148a9f0 000000000000002f ffffffff813c98c1 ffff88007c4451f8
[  541.031148]  0000000000000000 0000000000000000 ffffffff813d3540 ffff88007fc03d18
[  541.031150]  0000880000000006 ffff88007c445000 ffffffffa0194160 0000000000000000
[  541.031152] Call Trace:
[  541.031153]  <IRQ>  [<ffffffff8148a9f0>] ? dump_stack+0xd/0x17
[  541.031180]  [<ffffffff813c98c1>] ? __dev_set_promiscuity+0x101/0x180
[  541.031183]  [<ffffffff813d3540>] ? __hw_addr_create_ex+0x60/0xc0
[  541.031185]  [<ffffffff813cfe1a>] ? __dev_set_rx_mode+0xaa/0xc0
[  541.031189]  [<ffffffff813d3a81>] ? __dev_mc_add+0x61/0x90
[  541.031198]  [<ffffffffa01dcf9c>] ? igmp6_group_added+0xfc/0x1a0 [ipv6]
[  541.031208]  [<ffffffff8111237b>] ? kmem_cache_alloc+0xcb/0xd0
[  541.031212]  [<ffffffffa01ddcd7>] ? ipv6_dev_mc_inc+0x267/0x300 [ipv6]
[  541.031216]  [<ffffffffa01c2fae>] ? addrconf_join_solict+0x2e/0x40 [ipv6]
[  541.031219]  [<ffffffffa01ba2e9>] ? ipv6_dev_ac_inc+0x159/0x1f0 [ipv6]
[  541.031223]  [<ffffffffa01c0772>] ? addrconf_join_anycast+0x92/0xa0 [ipv6]
[  541.031226]  [<ffffffffa01c311e>] ? __ipv6_ifa_notify+0x11e/0x1e0 [ipv6]
[  541.031229]  [<ffffffffa01c3213>] ? ipv6_ifa_notify+0x33/0x50 [ipv6]
[  541.031233]  [<ffffffffa01c36c8>] ? addrconf_dad_completed+0x28/0x100 [ipv6]
[  541.031241]  [<ffffffff81075c1d>] ? task_cputime+0x2d/0x50
[  541.031244]  [<ffffffffa01c38d6>] ? addrconf_dad_timer+0x136/0x150 [ipv6]
[  541.031247]  [<ffffffffa01c37a0>] ? addrconf_dad_completed+0x100/0x100 [ipv6]
[  541.031255]  [<ffffffff8105313a>] ? call_timer_fn.isra.22+0x2a/0x90
[  541.031258]  [<ffffffffa01c37a0>] ? addrconf_dad_completed+0x100/0x100 [ipv6]
[  541.031261]  [<ffffffff81053531>] ? run_timer_softirq+0x1a1/0x260
[  541.031267]  [<ffffffff810350cf>] ? kvm_clock_read+0x1f/0x30
[  541.031272]  [<ffffffff810132a5>] ? sched_clock+0x5/0x10
[  541.031274]  [<ffffffff81074bd5>] ? sched_clock_local+0x15/0x80
[  541.031276]  [<ffffffff8104d586>] ? __do_softirq+0xd6/0x1b0
[  541.031282]  [<ffffffff8149109c>] ? call_softirq+0x1c/0x30
[  541.031284]  [<ffffffff8100d835>] ? do_softirq+0x75/0xb0
[  541.031286]  [<ffffffff8104d7ed>] ? irq_exit+0xbd/0xc0
[  541.031290]  [<ffffffff8102e718>] ? smp_apic_timer_interrupt+0x68/0xa0
[  541.031292]  [<ffffffff814908dd>] ? apic_timer_interrupt+0x6d/0x80
[  541.031293]  <EOI>  [<ffffffff81013ee0>] ? hard_enable_TSC+0x20/0x20
[  541.031296]  [<ffffffff81035412>] ? native_safe_halt+0x2/0x10
[  541.031298]  [<ffffffff81014619>] ? arch_cpu_idle+0x9/0x30
[  541.031299]  [<ffffffff81013ee5>] ? default_idle+0x5/0x10
[  541.031302]  [<ffffffff8108263a>] ? cpu_startup_entry+0x8a/0x180
[  541.031306]  [<ffffffff818d3e3e>] ? start_kernel+0x3ac/0x3b7
[  541.031309]  [<ffffffff818d38a9>] ? repair_env_string+0x5b/0x5b
[  541.031311]  [<ffffffff818d36bc>] ? x86_64_start_kernel+0xf6/0x105


Signed-off-by: Stephen Hemminger <stephen@...workplumber.org>

---
Patch is against -net (not net-next) because this is a bug fix.
Should be applied to -stable as well.

--- a/include/net/if_inet6.h	2014-03-17 10:53:06.386453341 -0700
+++ b/include/net/if_inet6.h	2014-03-17 11:01:42.383220298 -0700
@@ -59,6 +59,7 @@ struct inet6_ifaddr {
 	unsigned long		tstamp; /* updated timestamp */
 
 	struct timer_list	dad_timer;
+	struct work_struct	dad_work;
 
 	struct inet6_dev	*idev;
 	struct rt6_info		*rt;
--- a/net/ipv6/addrconf.c	2014-03-17 10:53:06.386453341 -0700
+++ b/net/ipv6/addrconf.c	2014-03-17 15:12:52.785628652 -0700
@@ -150,8 +150,10 @@ static struct rt6_info *addrconf_get_pre
 						  const struct net_device *dev,
 						  u32 flags, u32 noflags);
 
+static struct workqueue_struct *addrconf_wq;
 static void addrconf_dad_start(struct inet6_ifaddr *ifp);
 static void addrconf_dad_timer(unsigned long data);
+static void addrconf_dad_work(struct work_struct *work);
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
 static void addrconf_dad_run(struct inet6_dev *idev);
 static void addrconf_rs_timer(unsigned long data);
@@ -851,6 +853,7 @@ ipv6_add_addr(struct inet6_dev *idev, co
 	spin_lock_init(&ifa->state_lock);
 	setup_timer(&ifa->dad_timer, addrconf_dad_timer,
 		    (unsigned long)ifa);
+	INIT_WORK(&ifa->dad_work, addrconf_dad_work);
 	INIT_HLIST_NODE(&ifa->addr_lst);
 	ifa->scope = scope;
 	ifa->prefix_len = pfxlen;
@@ -3203,6 +3206,18 @@ out:
 	read_unlock_bh(&idev->lock);
 }
 
+/* DAD completion is handled in work queue */
+static void addrconf_dad_work(struct work_struct *work)
+{
+	struct inet6_ifaddr *ifp
+		= container_of(work, struct inet6_ifaddr, dad_work);
+
+	rtnl_lock();
+	addrconf_dad_completed(ifp);
+	rtnl_unlock();
+	in6_ifa_put(ifp);
+}
+
 static void addrconf_dad_timer(unsigned long data)
 {
 	struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
@@ -3234,9 +3249,8 @@ static void addrconf_dad_timer(unsigned
 		spin_unlock(&ifp->lock);
 		write_unlock(&idev->lock);
 
-		addrconf_dad_completed(ifp);
-
-		goto out;
+		queue_work(addrconf_wq, &ifp->dad_work);
+		return;
 	}
 
 	ifp->dad_probes--;
@@ -5244,6 +5258,12 @@ int __init addrconf_init(void)
 	if (err < 0)
 		goto out_addrlabel;
 
+	addrconf_wq = create_workqueue("addrconf");
+	if (!addrconf_wq) {
+		err = -ENOMEM;
+		goto out_nowq;
+	}
+
 	/* The addrconf netdev notifier requires that loopback_dev
 	 * has it's ipv6 private information allocated and setup
 	 * before it can bring up and give link-local addresses
@@ -5302,6 +5322,8 @@ errout:
 	rtnl_af_unregister(&inet6_ops);
 	unregister_netdevice_notifier(&ipv6_dev_notf);
 errlo:
+	destroy_workqueue(addrconf_wq);
+out_nowq:
 	unregister_pernet_subsys(&addrconf_ops);
 out_addrlabel:
 	ipv6_addr_label_cleanup();
@@ -5340,4 +5362,5 @@ void addrconf_cleanup(void)
 
 	del_timer(&addr_chk_timer);
 	rtnl_unlock();
+	destroy_workqueue(addrconf_wq);
 }
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ