]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
ipv6: Always allocate pcpu memory in a fib6_nh
authorDavid Ahern <dsahern@gmail.com>
Tue, 4 Jun 2019 01:37:03 +0000 (18:37 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Jun 2019 21:54:59 +0000 (14:54 -0700)
A recent commit had an unintended side effect with reject routes:
rt6i_pcpu is expected to always be initialized for all fib6_info except
the null entry. The commit mentioned below skips it for reject routes
and ends up leaking references to the loopback device. For example,

    ip netns add foo
    ip -netns foo li set lo up
    ip -netns foo -6 ro add blackhole 2001:db8:1::1
    ip netns exec foo ping6 2001:db8:1::1
    ip netns del foo

ends up spewing:
    unregister_netdevice: waiting for lo to become free. Usage count = 3

The fib_nh_common_init is not needed for reject routes (no ipv4 caching
or encaps), so move the alloc_percpu_gfp after it and adjust the goto label.

Fixes: f40b6ae2b612 ("ipv6: Move pcpu cached routes to fib6_nh")
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/route.c

index a72d01010cb6a734b2c4ee2dd865390d88e6a3b2..9b9a0159f7fdb059f7d08a6c39d8b2e96f313389 100644 (file)
@@ -3113,7 +3113,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
                                goto out;
                        }
                }
-               goto set_dev;
+               goto pcpu_alloc;
        }
 
        if (cfg->fc_flags & RTF_GATEWAY) {
@@ -3145,17 +3145,18 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
            !netif_carrier_ok(dev))
                fib6_nh->fib_nh_flags |= RTNH_F_LINKDOWN;
 
+       err = fib_nh_common_init(&fib6_nh->nh_common, cfg->fc_encap,
+                                cfg->fc_encap_type, cfg, gfp_flags, extack);
+       if (err)
+               goto out;
+
+pcpu_alloc:
        fib6_nh->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, gfp_flags);
        if (!fib6_nh->rt6i_pcpu) {
                err = -ENOMEM;
                goto out;
        }
 
-       err = fib_nh_common_init(&fib6_nh->nh_common, cfg->fc_encap,
-                                cfg->fc_encap_type, cfg, gfp_flags, extack);
-       if (err)
-               goto out;
-set_dev:
        fib6_nh->fib_nh_dev = dev;
        fib6_nh->fib_nh_oif = dev->ifindex;
        err = 0;