On Wed, Feb 8, 2017 at 5:56 AM, Dmitry Vyukov <dvyu...@google.com> wrote: > First dev->tstats was freed here: > > 1376 static int ipip6_tunnel_init(struct net_device *dev) > 1377 { > 1378 struct ip_tunnel *tunnel = netdev_priv(dev); > 1379 int err; > 1380 > 1381 tunnel->dev = dev; > 1382 tunnel->net = dev_net(dev); > 1383 strcpy(tunnel->parms.name, dev->name); > 1384 > 1385 ipip6_tunnel_bind_dev(dev); > 1386 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); > 1387 if (!dev->tstats) > 1388 return -ENOMEM; > 1389 > 1390 err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); > 1391 if (err) { > 1392 free_percpu(dev->tstats); > 1393 return err; > 1394 } > 1395 > 1396 return 0; > 1397 } > > And then again here: > > 1342 static void ipip6_dev_free(struct net_device *dev) > 1343 { > 1344 struct ip_tunnel *tunnel = netdev_priv(dev); > 1345 > 1346 dst_cache_destroy(&tunnel->dst_cache); > 1347 free_percpu(dev->tstats); > 1348 free_netdev(dev); > 1349 }
Probably we need to NULL dev->tstats in the ndo_init(), and ipip6 tunnel seems not the only one missing it.