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: <fce85b872c03cee379cb30ae46100ff42bea8e0d.1566807905.git.lucien.xin@gmail.com>
Date:   Mon, 26 Aug 2019 16:25:05 +0800
From:   Xin Long <lucien.xin@...il.com>
To:     network dev <netdev@...r.kernel.org>
Cc:     davem@...emloft.net,
        Steffen Klassert <steffen.klassert@...unet.com>
Subject: [PATCH net] xfrm: add NETDEV_UNREGISTER event process for xfrmi

When creating a xfrmi dev, it always holds the phydev. The xfrmi dev should
be deleted when the phydev is being unregistered, so that the phydev can be
put on time. Otherwise the phydev's deleting will get stuck:

  # ip link add dummy10 type dummy
  # ip link add xfrmi10 type xfrm dev dummy10
  # ip link del dummy10

The last command blocks and dmesg shows:

  unregister_netdevice: waiting for dummy10 to become free. Usage count = 1

This patch fixes it by adding NETDEV_UNREGISTER event process for xfrmi.

Fixes: f203b76d7809 ("xfrm: Add virtual xfrm interfaces")
Reported-by: Xiumei Mu <xmu@...hat.com>
Signed-off-by: Xin Long <lucien.xin@...il.com>
---
 net/xfrm/xfrm_interface.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 74868f9..f3de1f5 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -877,6 +877,35 @@ static const struct xfrm_if_cb xfrm_if_cb = {
 	.decode_session =	xfrmi_decode_session,
 };
 
+static int xfrmi_event(struct notifier_block *this, unsigned long e, void *ptr)
+{
+	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct xfrmi_net *xfrmn = net_generic(dev_net(dev), xfrmi_net_id);
+	struct xfrm_if *xi;
+	LIST_HEAD(list);
+
+	if (e != NETDEV_UNREGISTER)
+		return NOTIFY_DONE;
+
+	rcu_read_lock();
+	for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
+		if (xi->phydev != dev)
+			continue;
+		unregister_netdevice_queue(xi->dev, &list);
+	}
+	rcu_read_unlock();
+
+	if (list_empty(&list))
+		return NOTIFY_DONE;
+
+	unregister_netdevice_many(&list);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block xfrmi_notifier = {
+	.notifier_call  = xfrmi_event,
+};
+
 static int __init xfrmi_init(void)
 {
 	const char *msg;
@@ -906,6 +935,7 @@ static int __init xfrmi_init(void)
 		goto rtnl_link_failed;
 
 	xfrm_if_register_cb(&xfrm_if_cb);
+	register_netdevice_notifier(&xfrmi_notifier);
 
 	return err;
 
@@ -922,6 +952,7 @@ static int __init xfrmi_init(void)
 
 static void __exit xfrmi_fini(void)
 {
+	unregister_netdevice_notifier(&xfrmi_notifier);
 	xfrm_if_unregister_cb();
 	rtnl_link_unregister(&xfrmi_link_ops);
 	xfrmi4_fini();
-- 
2.1.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ