Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -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;