diff options
author | Eric Dumazet <edumazet@google.com> | 2015-11-02 20:08:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-11-02 22:54:45 -0500 |
commit | 4ece9009774596ee3df0acba65a324b7ea79387c (patch) | |
tree | 640ee475b32807af8c52f1f5d6172c97f0aee3e9 /net | |
parent | 8fa677d2706d325d71dab91bf6e6512c05214e37 (diff) |
sit: fix sit0 percpu double allocations
sit0 device allocates its percpu storage twice :
- One time in ipip6_tunnel_init()
- One time in ipip6_fb_tunnel_init()
Thus we leak 48 bytes per possible cpu per network namespace dismantle.
ipip6_fb_tunnel_init() can be much simpler and does not
return an error, and should be called after register_netdev()
Note that ipip6_tunnel_clone_6rd() also needs to be called
after register_netdev() (calling ipip6_tunnel_init())
Fixes: ebe084aafb7e ("sit: Use ipip6_tunnel_init as the ndo_init function.")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/sit.c | 26 |
1 files changed, 4 insertions, 22 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 94428fd85b2f..dcccae86190f 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -1394,34 +1394,20 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
1394 | return 0; | 1394 | return 0; |
1395 | } | 1395 | } |
1396 | 1396 | ||
1397 | static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | 1397 | static void __net_init ipip6_fb_tunnel_init(struct net_device *dev) |
1398 | { | 1398 | { |
1399 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1399 | struct ip_tunnel *tunnel = netdev_priv(dev); |
1400 | struct iphdr *iph = &tunnel->parms.iph; | 1400 | struct iphdr *iph = &tunnel->parms.iph; |
1401 | struct net *net = dev_net(dev); | 1401 | struct net *net = dev_net(dev); |
1402 | struct sit_net *sitn = net_generic(net, sit_net_id); | 1402 | struct sit_net *sitn = net_generic(net, sit_net_id); |
1403 | 1403 | ||
1404 | tunnel->dev = dev; | ||
1405 | tunnel->net = dev_net(dev); | ||
1406 | |||
1407 | iph->version = 4; | 1404 | iph->version = 4; |
1408 | iph->protocol = IPPROTO_IPV6; | 1405 | iph->protocol = IPPROTO_IPV6; |
1409 | iph->ihl = 5; | 1406 | iph->ihl = 5; |
1410 | iph->ttl = 64; | 1407 | iph->ttl = 64; |
1411 | 1408 | ||
1412 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); | ||
1413 | if (!dev->tstats) | ||
1414 | return -ENOMEM; | ||
1415 | |||
1416 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | ||
1417 | if (!tunnel->dst_cache) { | ||
1418 | free_percpu(dev->tstats); | ||
1419 | return -ENOMEM; | ||
1420 | } | ||
1421 | |||
1422 | dev_hold(dev); | 1409 | dev_hold(dev); |
1423 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); | 1410 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); |
1424 | return 0; | ||
1425 | } | 1411 | } |
1426 | 1412 | ||
1427 | static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[]) | 1413 | static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[]) |
@@ -1831,23 +1817,19 @@ static int __net_init sit_init_net(struct net *net) | |||
1831 | */ | 1817 | */ |
1832 | sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; | 1818 | sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; |
1833 | 1819 | ||
1834 | err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); | ||
1835 | if (err) | ||
1836 | goto err_dev_free; | ||
1837 | |||
1838 | ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn); | ||
1839 | err = register_netdev(sitn->fb_tunnel_dev); | 1820 | err = register_netdev(sitn->fb_tunnel_dev); |
1840 | if (err) | 1821 | if (err) |
1841 | goto err_reg_dev; | 1822 | goto err_reg_dev; |
1842 | 1823 | ||
1824 | ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn); | ||
1825 | ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); | ||
1826 | |||
1843 | t = netdev_priv(sitn->fb_tunnel_dev); | 1827 | t = netdev_priv(sitn->fb_tunnel_dev); |
1844 | 1828 | ||
1845 | strcpy(t->parms.name, sitn->fb_tunnel_dev->name); | 1829 | strcpy(t->parms.name, sitn->fb_tunnel_dev->name); |
1846 | return 0; | 1830 | return 0; |
1847 | 1831 | ||
1848 | err_reg_dev: | 1832 | err_reg_dev: |
1849 | dev_put(sitn->fb_tunnel_dev); | ||
1850 | err_dev_free: | ||
1851 | ipip6_dev_free(sitn->fb_tunnel_dev); | 1833 | ipip6_dev_free(sitn->fb_tunnel_dev); |
1852 | err_alloc_dev: | 1834 | err_alloc_dev: |
1853 | return err; | 1835 | return err; |