aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-11-02 20:08:19 -0500
committerDavid S. Miller <davem@davemloft.net>2015-11-02 22:54:45 -0500
commit4ece9009774596ee3df0acba65a324b7ea79387c (patch)
tree640ee475b32807af8c52f1f5d6172c97f0aee3e9 /net
parent8fa677d2706d325d71dab91bf6e6512c05214e37 (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.c26
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
1397static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) 1397static 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
1427static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[]) 1413static 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
1848err_reg_dev: 1832err_reg_dev:
1849 dev_put(sitn->fb_tunnel_dev);
1850err_dev_free:
1851 ipip6_dev_free(sitn->fb_tunnel_dev); 1833 ipip6_dev_free(sitn->fb_tunnel_dev);
1852err_alloc_dev: 1834err_alloc_dev:
1853 return err; 1835 return err;