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-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 9 Feb 2022 22:10:15 -0800
From:   Eric Dumazet <edumazet@...gle.com>
To:     Jakub Kicinski <kuba@...nel.org>
Cc:     Xin Long <lucien.xin@...il.com>,
        network dev <netdev@...r.kernel.org>,
        davem <davem@...emloft.net>,
        Ziyang Xuan <william.xuanziyang@...wei.com>
Subject: Re: [PATCH net 2/2] vlan: move dev_put into vlan_dev_uninit

On Wed, Feb 9, 2022 at 9:49 PM Eric Dumazet <edumazet@...gle.com> wrote:

>
> BTW, I have the plan of generalizing blackhole_netdev for IPv6,
> meaning that we could perhaps get rid of the dependency
> about loopback dev, being the last device in a netns being dismantled.

Untested patch to give more ideas:
(Main incentive is that we are still chasing a unregister_device bug,
that I now think is related to IPv6 idev leaking somewhere)


diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4f402bc38f056e08f3761e63a7bc7a51e54e9384..02d31d4fcab3b3d529c4fe3260216ecee1108e82
100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -372,7 +372,7 @@ static struct inet6_dev *ipv6_add_dev(struct
net_device *dev)

        ASSERT_RTNL();

-       if (dev->mtu < IPV6_MIN_MTU)
+       if (dev->mtu < IPV6_MIN_MTU && dev != blackhole_netdev)
                return ERR_PTR(-EINVAL);

        ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL);
@@ -400,21 +400,22 @@ static struct inet6_dev *ipv6_add_dev(struct
net_device *dev)
        /* We refer to the device */
        dev_hold_track(dev, &ndev->dev_tracker, GFP_KERNEL);

-       if (snmp6_alloc_dev(ndev) < 0) {
-               netdev_dbg(dev, "%s: cannot allocate memory for statistics\n",
-                          __func__);
-               neigh_parms_release(&nd_tbl, ndev->nd_parms);
-               dev_put_track(dev, &ndev->dev_tracker);
-               kfree(ndev);
-               return ERR_PTR(err);
-       }
+       if (dev != blackhole_netdev) {
+               if (snmp6_alloc_dev(ndev) < 0) {
+                       netdev_dbg(dev, "%s: cannot allocate memory
for statistics\n",
+                                  __func__);
+                       neigh_parms_release(&nd_tbl, ndev->nd_parms);
+                       dev_put_track(dev, &ndev->dev_tracker);
+                       kfree(ndev);
+                       return ERR_PTR(err);
+               }

-       if (snmp6_register_dev(ndev) < 0) {
-               netdev_dbg(dev, "%s: cannot create /proc/net/dev_snmp6/%s\n",
-                          __func__, dev->name);
-               goto err_release;
+               if (snmp6_register_dev(ndev) < 0) {
+                       netdev_dbg(dev, "%s: cannot create
/proc/net/dev_snmp6/%s\n",
+                                  __func__, dev->name);
+                       goto err_release;
+               }
        }
-
        /* One reference from device. */
        refcount_set(&ndev->refcnt, 1);

@@ -445,25 +446,28 @@ static struct inet6_dev *ipv6_add_dev(struct
net_device *dev)

        ipv6_mc_init_dev(ndev);
        ndev->tstamp = jiffies;
-       err = addrconf_sysctl_register(ndev);
-       if (err) {
-               ipv6_mc_destroy_dev(ndev);
-               snmp6_unregister_dev(ndev);
-               goto err_release;
+       if (dev != blackhole_netdev) {
+               err = addrconf_sysctl_register(ndev);
+               if (err) {
+                       ipv6_mc_destroy_dev(ndev);
+                       snmp6_unregister_dev(ndev);
+                       goto err_release;
+               }
        }
        /* protected by rtnl_lock */
        rcu_assign_pointer(dev->ip6_ptr, ndev);

-       /* Join interface-local all-node multicast group */
-       ipv6_dev_mc_inc(dev, &in6addr_interfacelocal_allnodes);
+       if (dev != blackhole_netdev) {
+               /* Join interface-local all-node multicast group */
+               ipv6_dev_mc_inc(dev, &in6addr_interfacelocal_allnodes);

-       /* Join all-node multicast group */
-       ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes);
-
-       /* Join all-router multicast group if forwarding is set */
-       if (ndev->cnf.forwarding && (dev->flags & IFF_MULTICAST))
-               ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
+               /* Join all-node multicast group */
+               ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes);

+               /* Join all-router multicast group if forwarding is set */
+               if (ndev->cnf.forwarding && (dev->flags & IFF_MULTICAST))
+                       ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
+       }
        return ndev;

 err_release:
@@ -7233,26 +7237,8 @@ int __init addrconf_init(void)
                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
-        * to other devices which are up.
-        *
-        * Unfortunately, loopback_dev is not necessarily the first
-        * entry in the global dev_base list of net devices.  In fact,
-        * it is likely to be the very last entry on that list.
-        * So this causes the notifier registry below to try and
-        * give link-local addresses to all devices besides loopback_dev
-        * first, then loopback_dev, which cases all the non-loopback_dev
-        * devices to fail to get a link-local address.
-        *
-        * So, as a temporary fix, allocate the ipv6 structure for
-        * loopback_dev first by hand.
-        * Longer term, all of the dependencies ipv6 has upon the loopback
-        * device and it being up should be removed.
-        */
        rtnl_lock();
-       idev = ipv6_add_dev(init_net.loopback_dev);
+       idev = ipv6_add_dev(blackhole_netdev);
        rtnl_unlock();
        if (IS_ERR(idev)) {
                err = PTR_ERR(idev);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f4884cda13b92e72d041680cbabfee2e07ec0f10..dc9d26a77c48f649ec39084c539d45b378474a35
100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -160,12 +160,8 @@ void rt6_uncached_list_del(struct rt6_info *rt)

 static void rt6_uncached_list_flush_dev(struct net *net, struct
net_device *dev)
 {
-       struct net_device *loopback_dev = net->loopback_dev;
        int cpu;

-       if (dev == loopback_dev)
-               return;
-
        for_each_possible_cpu(cpu) {
                struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu);
                struct rt6_info *rt;
@@ -176,7 +172,7 @@ static void rt6_uncached_list_flush_dev(struct net
*net, struct net_device *dev)
                        struct net_device *rt_dev = rt->dst.dev;

                        if (rt_idev->dev == dev) {
-                               rt->rt6i_idev = in6_dev_get(loopback_dev);
+                               rt->rt6i_idev = in6_dev_get(blackhole_netdev);
                                in6_dev_put(rt_idev);
                        }

@@ -373,13 +369,12 @@ static void ip6_dst_ifdown(struct dst_entry
*dst, struct net_device *dev,
 {
        struct rt6_info *rt = (struct rt6_info *)dst;
        struct inet6_dev *idev = rt->rt6i_idev;
-       struct net_device *loopback_dev =
-               dev_net(dev)->loopback_dev;

-       if (idev && idev->dev != loopback_dev) {
-               struct inet6_dev *loopback_idev = in6_dev_get(loopback_dev);
-               if (loopback_idev) {
-                       rt->rt6i_idev = loopback_idev;
+       if (idev && idev->dev != blackhole_netdev) {
+               struct inet6_dev *blackhole_idev =
in6_dev_get(blackhole_netdev);
+
+               if (blackhole_idev) {
+                       rt->rt6i_idev = blackhole_idev;
                        in6_dev_put(idev);
                }
        }

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ