Commit 7dd73168 authored by David Ahern's avatar David Ahern Committed by David S. Miller

ipv6: Always allocate pcpu memory in a fib6_nh

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: f40b6ae2 ("ipv6: Move pcpu cached routes to fib6_nh")
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1e007181
...@@ -3113,7 +3113,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh, ...@@ -3113,7 +3113,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
goto out; goto out;
} }
} }
goto set_dev; goto pcpu_alloc;
} }
if (cfg->fc_flags & RTF_GATEWAY) { if (cfg->fc_flags & RTF_GATEWAY) {
...@@ -3145,17 +3145,18 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh, ...@@ -3145,17 +3145,18 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
!netif_carrier_ok(dev)) !netif_carrier_ok(dev))
fib6_nh->fib_nh_flags |= RTNH_F_LINKDOWN; 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); fib6_nh->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, gfp_flags);
if (!fib6_nh->rt6i_pcpu) { if (!fib6_nh->rt6i_pcpu) {
err = -ENOMEM; err = -ENOMEM;
goto out; 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_dev = dev;
fib6_nh->fib_nh_oif = dev->ifindex; fib6_nh->fib_nh_oif = dev->ifindex;
err = 0; err = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment