All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice
@ 2017-05-02  5:58 gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 01/12] driver: dummy: Fix one possbile memleak " gfree.wind
                   ` (14 more replies)
  0 siblings, 15 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02  5:58 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

These following drivers allocate kinds of resources in its ndo_init
func, free some of them or all in the destructor func. Then there is
one memleak that some errors happen after register_netdevice invokes
the ndo_init callback. Because only the ndo_uninit callback is invoked
in the error handler of register_netdevice, but destructor not.

In my original approach, I tried to free the resources in the newlink
func when fail to register_netdevice, like destructor did except not
free the net_dev. This method is not good when destructor is changed,
and the memleak could be not fixed when there is no newlink callback.

Now create one new func used to free the resources in the destructor,
and the ndo_uninit func also could invokes it when fail to register
the net_device by comparing the dev->reg_state with NETREG_UNINITIALIZED.
If there is no existing ndo_uninit, just add one.

This solution doesn't only make sure free all resources in any case,
but also follows the original desgin that some resources could be kept
until the destructor executes normally after register the device
successfully.

Gao Feng (12):
  driver: dummy: Fix one possbile memleak when fail to
    register_netdevice
  driver: ifb: Fix one possbile memleak when fail to register_netdevice
  driver: loopback: Fix one possbile memleak when fail to
    register_netdevice
  driver: team: Fix one possbile memleak when fail to register_netdevice
  driver: veth: Fix one possbile memleak when fail to register_netdevice
  net: ip6_gre: Fix one possbile memleak when fail to register_netdevice
  ip6_tunnel: Fix one possbile memleak when fail to register_netdevice
  net: ip6_vti: Fix one possbile memleak when fail to register_netdevice
  net: ip_tunnel: Fix one possbile memleak when fail to
    register_netdevice
  net: sit: Fix one possbile memleak when fail to register_netdevice
  net: vlan: Fix one possbile memleak when fail to register_netdevice
  net: batman-adv: Fix one possbile memleak when fail to
    register_netdevice

 drivers/net/dummy.c             | 14 +++++++++++---
 drivers/net/ifb.c               | 33 +++++++++++++++++++++++----------
 drivers/net/loopback.c          | 15 ++++++++++++++-
 drivers/net/team/team.c         | 15 ++++++++++++---
 drivers/net/veth.c              | 15 ++++++++++++++-
 net/8021q/vlan_dev.c            | 17 +++++++++++++----
 net/batman-adv/soft-interface.c | 18 +++++++++++++++---
 net/ipv4/ip_tunnel.c            | 11 ++++++++++-
 net/ipv6/ip6_gre.c              | 17 +++++++++++++----
 net/ipv6/ip6_tunnel.c           | 11 ++++++++++-
 net/ipv6/ip6_vti.c              | 11 ++++++++++-
 net/ipv6/sit.c                  | 17 +++++++++++++----
 12 files changed, 158 insertions(+), 36 deletions(-)

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH net v4 01/12] driver: dummy: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
@ 2017-05-02  5:58 ` gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 02/12] driver: ifb: " gfree.wind
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02  5:58 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The dummy driver allocates dev->dstats and priv->vfinfo in its
ndo_init func dummy_dev_init, free the dev->dstats in the ndo_uninit
and free the priv->vfinfo in its destructor func. Then there is one
memleak that some errors happen after register_netdevice invokes the
ndo_init callback. Because only the ndo_uninit callback is invoked in
the error handler of register_netdevice, but destructor not.

Now create one new func dummy_destructor_free to free the mem in the
destructor, and the ndo_uninit func also invokes it when fail to
register the dummy device.

It's not only free all resources, but also follow the original desgin
that the priv->vfinfo is freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 drivers/net/dummy.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 2c80611..0b3c1cc 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -153,9 +153,19 @@ static int dummy_dev_init(struct net_device *dev)
 	return 0;
 }
 
+static void dummy_destructor_free(struct net_device *dev)
+{
+	struct dummy_priv *priv = netdev_priv(dev);
+
+	kfree(priv->vfinfo);
+}
+
 static void dummy_dev_uninit(struct net_device *dev)
 {
 	free_percpu(dev->dstats);
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		dummy_destructor_free(dev);
 }
 
 static int dummy_change_carrier(struct net_device *dev, bool new_carrier)
@@ -310,9 +320,7 @@ static void dummy_get_drvinfo(struct net_device *dev,
 
 static void dummy_free_netdev(struct net_device *dev)
 {
-	struct dummy_priv *priv = netdev_priv(dev);
-
-	kfree(priv->vfinfo);
+	dummy_destructor_free(dev);
 	free_netdev(dev);
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 02/12] driver: ifb: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 01/12] driver: dummy: Fix one possbile memleak " gfree.wind
@ 2017-05-02  5:58 ` gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 03/12] driver: loopback: " gfree.wind
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02  5:58 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The ifb driver allocates some resources in its ndo_init func, and free
them in its destructor func. Then there is one memleak that some errors
happen after register_netdevice invokes the ndo_init callback. Because
the destructor would not be invoked to free the resources.

Now create one new func ifb_destructor_free to free the mem in the
destructor, and add ndo_uninit func also invokes it when fail to register
the ifb device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 drivers/net/ifb.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 312fce7..b25aea1 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -180,6 +180,27 @@ static int ifb_dev_init(struct net_device *dev)
 	return 0;
 }
 
+static void ifb_destructor_free(struct net_device *dev)
+{
+	struct ifb_dev_private *dp = netdev_priv(dev);
+	struct ifb_q_private *txp = dp->tx_private;
+	int i;
+
+	for (i = 0; i < dev->num_tx_queues; i++, txp++) {
+		tasklet_kill(&txp->ifb_tasklet);
+		__skb_queue_purge(&txp->rq);
+		__skb_queue_purge(&txp->tq);
+	}
+	kfree(dp->tx_private);
+}
+
+static void ifb_dev_uninit(struct net_device *dev)
+{
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		ifb_destructor_free(dev);
+}
+
 static const struct net_device_ops ifb_netdev_ops = {
 	.ndo_open	= ifb_open,
 	.ndo_stop	= ifb_close,
@@ -187,6 +208,7 @@ static int ifb_dev_init(struct net_device *dev)
 	.ndo_start_xmit	= ifb_xmit,
 	.ndo_validate_addr = eth_validate_addr,
 	.ndo_init	= ifb_dev_init,
+	.ndo_uninit	= ifb_dev_uninit,
 };
 
 #define IFB_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG  | NETIF_F_FRAGLIST	| \
@@ -197,16 +219,7 @@ static int ifb_dev_init(struct net_device *dev)
 
 static void ifb_dev_free(struct net_device *dev)
 {
-	struct ifb_dev_private *dp = netdev_priv(dev);
-	struct ifb_q_private *txp = dp->tx_private;
-	int i;
-
-	for (i = 0; i < dev->num_tx_queues; i++,txp++) {
-		tasklet_kill(&txp->ifb_tasklet);
-		__skb_queue_purge(&txp->rq);
-		__skb_queue_purge(&txp->tq);
-	}
-	kfree(dp->tx_private);
+	ifb_destructor_free(dev);
 	free_netdev(dev);
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 03/12] driver: loopback: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 01/12] driver: dummy: Fix one possbile memleak " gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 02/12] driver: ifb: " gfree.wind
@ 2017-05-02  5:58 ` gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 04/12] driver: team: " gfree.wind
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02  5:58 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The loopback driver allocates some resources in its ndo_init func, and
free them in its destructor func. Then there is one memleak that some
errors happen after register_netdevice invokes the ndo_init callback.
Because the destructor would not be invoked to free the resources.

Now create one new func loopback_destructor_free to free the mem in
the destructor, and add ndo_uninit func also invokes it when fail to
register the loopback device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 drivers/net/loopback.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b23b719..d7c1016 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -141,15 +141,28 @@ static int loopback_dev_init(struct net_device *dev)
 	return 0;
 }
 
-static void loopback_dev_free(struct net_device *dev)
+static void loopback_destructor_free(struct net_device *dev)
 {
 	dev_net(dev)->loopback_dev = NULL;
 	free_percpu(dev->lstats);
+}
+
+static void loopback_dev_uninit(struct net_device *dev)
+{
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		loopback_destructor_free(dev);
+}
+
+static void loopback_dev_free(struct net_device *dev)
+{
+	loopback_destructor_free(dev);
 	free_netdev(dev);
 }
 
 static const struct net_device_ops loopback_ops = {
 	.ndo_init      = loopback_dev_init,
+	.ndo_uninit = loopback_dev_uninit,
 	.ndo_start_xmit= loopback_xmit,
 	.ndo_get_stats64 = loopback_get_stats64,
 	.ndo_set_mac_address = eth_mac_addr,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 04/12] driver: team: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (2 preceding siblings ...)
  2017-05-02  5:58 ` [PATCH net v4 03/12] driver: loopback: " gfree.wind
@ 2017-05-02  5:58 ` gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 05/12] driver: veth: " gfree.wind
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02  5:58 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The team driver allocates some resources in its ndo_init func, and
free some of them in its destructor func. Then there is one memleak
that some errors happen after register_netdevice invokes the ndo_init
callback. Because only the ndo_uninit callback is invoked in the error
handler of register_netdevice, but destructor not.

Now create one new func team_destructor_free to free the mem in the
destructor, and ndo_uninit func also invokes it when fail to register
the team device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 drivers/net/team/team.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 85c0124..d8dd203 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1619,6 +1619,13 @@ static int team_init(struct net_device *dev)
 	return err;
 }
 
+static void team_destructor_free(struct net_device *dev)
+{
+	struct team *team = netdev_priv(dev);
+
+	free_percpu(team->pcpu_stats);
+}
+
 static void team_uninit(struct net_device *dev)
 {
 	struct team *team = netdev_priv(dev);
@@ -1636,13 +1643,15 @@ static void team_uninit(struct net_device *dev)
 	team_queue_override_fini(team);
 	mutex_unlock(&team->lock);
 	netdev_change_features(dev);
+
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		team_destructor_free(dev);
 }
 
 static void team_destructor(struct net_device *dev)
 {
-	struct team *team = netdev_priv(dev);
-
-	free_percpu(team->pcpu_stats);
+	team_destructor_free(dev);
 	free_netdev(dev);
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 05/12] driver: veth: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (3 preceding siblings ...)
  2017-05-02  5:58 ` [PATCH net v4 04/12] driver: team: " gfree.wind
@ 2017-05-02  5:58 ` gfree.wind
  2017-05-02  5:58 ` [PATCH net v4 06/12] net: ip6_gre: " gfree.wind
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02  5:58 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The veth driver allocates some resources in its ndo_init func, and
free them in its destructor func. Then there is one memleak that some
errors happen after register_netdevice invokes the ndo_init callback.
Because the destructor would not be invoked to free the resources.

Now create one new func veth_destructor_free to free the mem in the
destructor, and add ndo_uninit func also invokes it when fail to register
the veth device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 drivers/net/veth.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 8c39d6d..418376a 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -224,9 +224,21 @@ static int veth_dev_init(struct net_device *dev)
 	return 0;
 }
 
-static void veth_dev_free(struct net_device *dev)
+static void veth_destructor_free(struct net_device *dev)
 {
 	free_percpu(dev->vstats);
+}
+
+static void veth_dev_uninit(struct net_device *dev)
+{
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		veth_destructor_free(dev);
+}
+
+static void veth_dev_free(struct net_device *dev)
+{
+	veth_destructor_free(dev);
 	free_netdev(dev);
 }
 
@@ -284,6 +296,7 @@ static void veth_set_rx_headroom(struct net_device *dev, int new_hr)
 
 static const struct net_device_ops veth_netdev_ops = {
 	.ndo_init            = veth_dev_init,
+	.ndo_uninit          = veth_dev_uninit,
 	.ndo_open            = veth_open,
 	.ndo_stop            = veth_close,
 	.ndo_start_xmit      = veth_xmit,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 06/12] net: ip6_gre: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (4 preceding siblings ...)
  2017-05-02  5:58 ` [PATCH net v4 05/12] driver: veth: " gfree.wind
@ 2017-05-02  5:58 ` gfree.wind
  2017-05-02  6:59 ` [PATCH net v4 07/12] ip6_tunnel: " gfree.wind
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02  5:58 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The ip6_gre allocates some resources in its ndo_init func, and
free some of them in its destructor func. Then there is one memleak
that some errors happen after register_netdevice invokes the ndo_init
callback. Because only the ndo_uninit callback is invoked in the error
handler of register_netdevice, but destructor not.

Now create one new func ip6_gre_destructor_free to free the mem in
the destructor, and ndo_uninit func also invokes it when fail to
register the ip6_gre device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 net/ipv6/ip6_gre.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 6fcb7cb..e53c3ac 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -355,6 +355,14 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net,
 	return NULL;
 }
 
+static void ip6gre_destructor_free(struct net_device *dev)
+{
+	struct ip6_tnl *t = netdev_priv(dev);
+
+	dst_cache_destroy(&t->dst_cache);
+	free_percpu(dev->tstats);
+}
+
 static void ip6gre_tunnel_uninit(struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
@@ -363,6 +371,10 @@ static void ip6gre_tunnel_uninit(struct net_device *dev)
 	ip6gre_tunnel_unlink(ign, t);
 	dst_cache_reset(&t->dst_cache);
 	dev_put(dev);
+
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		ip6gre_destructor_free(dev);
 }
 
 
@@ -981,10 +993,7 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev,
 
 static void ip6gre_dev_free(struct net_device *dev)
 {
-	struct ip6_tnl *t = netdev_priv(dev);
-
-	dst_cache_destroy(&t->dst_cache);
-	free_percpu(dev->tstats);
+	ip6gre_destructor_free(dev);
 	free_netdev(dev);
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 07/12] ip6_tunnel: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (5 preceding siblings ...)
  2017-05-02  5:58 ` [PATCH net v4 06/12] net: ip6_gre: " gfree.wind
@ 2017-05-02  6:59 ` gfree.wind
  2017-05-02 11:10 ` [PATCH net v4 00/12] Fix possbile memleaks " Gao Feng
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02  6:59 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The ip6_tunnel allocates some resources in its ndo_init func, and
free some of them in its destructor func. Then there is one memleak
that some errors happen after register_netdevice invokes the ndo_init
callback. Because only the ndo_uninit callback is invoked in the error
handler of register_netdevice, but destructor not.

Now create one new func ip6_tnl_destructor_free to free the mem in
the destructor, and ndo_uninit func also invokes it when fail to
register the ip6_tunnel device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 net/ipv6/ip6_tunnel.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a9692ec..7dcb234 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -247,13 +247,18 @@ static struct net_device_stats *ip6_get_stats(struct net_device *dev)
 	}
 }
 
-static void ip6_dev_free(struct net_device *dev)
+static void ip6_tnl_destructor_free(struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 
 	gro_cells_destroy(&t->gro_cells);
 	dst_cache_destroy(&t->dst_cache);
 	free_percpu(dev->tstats);
+}
+
+static void ip6_dev_free(struct net_device *dev)
+{
+	ip6_tnl_destructor_free(dev);
 	free_netdev(dev);
 }
 
@@ -387,6 +392,10 @@ static struct ip6_tnl *ip6_tnl_locate(struct net *net,
 		ip6_tnl_unlink(ip6n, t);
 	dst_cache_reset(&t->dst_cache);
 	dev_put(dev);
+
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		ip6_tnl_destructor_free(dev);
 }
 
 /**
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* RE: [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (6 preceding siblings ...)
  2017-05-02  6:59 ` [PATCH net v4 07/12] ip6_tunnel: " gfree.wind
@ 2017-05-02 11:10 ` Gao Feng
  2017-05-02 13:34 ` [PATCH net v4 08/12] net: ip6_vti: Fix one possbile memleak " gfree.wind
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Gao Feng @ 2017-05-02 11:10 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev

Hi all,

> From: gfree.wind@foxmail.com [mailto:gfree.wind@foxmail.com]
> Sent: Tuesday, May 2, 2017 1:59 PM
>  drivers/net/dummy.c             | 14 +++++++++++---
>  drivers/net/ifb.c               | 33 +++++++++++++++++++++++----------
>  drivers/net/loopback.c          | 15 ++++++++++++++-
>  drivers/net/team/team.c         | 15 ++++++++++++---
>  drivers/net/veth.c              | 15 ++++++++++++++-
>  net/8021q/vlan_dev.c            | 17 +++++++++++++----
>  net/batman-adv/soft-interface.c | 18 +++++++++++++++---
>  net/ipv4/ip_tunnel.c            | 11 ++++++++++-
>  net/ipv6/ip6_gre.c              | 17 +++++++++++++----
>  net/ipv6/ip6_tunnel.c           | 11 ++++++++++-
>  net/ipv6/ip6_vti.c              | 11 ++++++++++-
>  net/ipv6/sit.c                  | 17 +++++++++++++----
>  12 files changed, 158 insertions(+), 36 deletions(-)
> 
> --
>  v4: Make patches as one sery of patches, per David Miler
>  v3: Split one patch to multiple commits, per David Ahern
>  v2: Move the free in ndo_uninit when fail to register, per Herbert Xu
>  v1: initial version
> 
> 

Because I sent these patches too fast today, so that my email server blocks
my account today.
The left patches (08~12) would be sent after my account is unlocked. 

Maybe tomorrow.
I am very sorry about this, and try to change another mail server next time.

Best Regards
Feng

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH net v4 08/12] net: ip6_vti: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (7 preceding siblings ...)
  2017-05-02 11:10 ` [PATCH net v4 00/12] Fix possbile memleaks " Gao Feng
@ 2017-05-02 13:34 ` gfree.wind
  2017-05-02 13:37 ` [PATCH net v4 09/12] net: ip_tunnel: " gfree.wind
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02 13:34 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The ip6_vti allocates some resources in its ndo_init func, and
free some of them in its destructor func. Then there is one memleak
that some errors happen after register_netdevice invokes the ndo_init
callback. Because only the ndo_uninit callback is invoked in the error
handler of register_netdevice, but destructor not.

Now create one new func vti6_destructor_free to free the mem in
the destructor, and ndo_uninit func also invokes it when fail to
register the vti6 device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 net/ipv6/ip6_vti.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 3d8a3b6..3b3f49a 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -177,9 +177,14 @@ struct vti6_net {
 	}
 }
 
-static void vti6_dev_free(struct net_device *dev)
+static void vti6_destructor_free(struct net_device *dev)
 {
 	free_percpu(dev->tstats);
+}
+
+static void vti6_dev_free(struct net_device *dev)
+{
+	vti6_destructor_free(dev);
 	free_netdev(dev);
 }
 
@@ -296,6 +301,10 @@ static void vti6_dev_uninit(struct net_device *dev)
 	else
 		vti6_tnl_unlink(ip6n, t);
 	dev_put(dev);
+
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		vti6_destructor_free(dev);
 }
 
 static int vti6_rcv(struct sk_buff *skb)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 09/12] net: ip_tunnel: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (8 preceding siblings ...)
  2017-05-02 13:34 ` [PATCH net v4 08/12] net: ip6_vti: Fix one possbile memleak " gfree.wind
@ 2017-05-02 13:37 ` gfree.wind
  2017-05-02 13:39 ` [PATCH net v4 10/12] net: sit: " gfree.wind
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02 13:37 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The ip_tunnel allocates some resources in its ndo_init func, and
free some of them in its destructor func. Then there is one memleak
that some errors happen after register_netdevice invokes the ndo_init
callback. Because only the ndo_uninit callback is invoked in the error
handler of register_netdevice, but destructor not.

Now create one new func ip_tunnel_destructor_free to free the mem in
the destructor, and ndo_uninit func also invokes it when fail to
register the ip_tunnel device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 net/ipv4/ip_tunnel.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 823abae..96a3005 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -954,13 +954,18 @@ int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
 
-static void ip_tunnel_dev_free(struct net_device *dev)
+static void ip_tunnel_destructor_free(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 
 	gro_cells_destroy(&tunnel->gro_cells);
 	dst_cache_destroy(&tunnel->dst_cache);
 	free_percpu(dev->tstats);
+}
+
+static void ip_tunnel_dev_free(struct net_device *dev)
+{
+	ip_tunnel_destructor_free(dev);
 	free_netdev(dev);
 }
 
@@ -1192,6 +1197,10 @@ void ip_tunnel_uninit(struct net_device *dev)
 		ip_tunnel_del(itn, netdev_priv(dev));
 
 	dst_cache_reset(&tunnel->dst_cache);
+
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		ip_tunnel_destructor_free(dev);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 10/12] net: sit: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (9 preceding siblings ...)
  2017-05-02 13:37 ` [PATCH net v4 09/12] net: ip_tunnel: " gfree.wind
@ 2017-05-02 13:39 ` gfree.wind
  2017-05-02 13:41 ` [PATCH net v4 11/12] net: vlan: " gfree.wind
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02 13:39 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The ipip6 allocates some resources in its ndo_init func, and
free some of them in its destructor func. Then there is one memleak
that some errors happen after register_netdevice invokes the ndo_init
callback. Because only the ndo_uninit callback is invoked in the error
handler of register_netdevice, but destructor not.

Now create one new func ipip6_destructor_free to free the mem in
the destructor, and ndo_uninit func also invokes it when fail to
register the ipip6 device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 net/ipv6/sit.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 99853c6..28c1649 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -464,6 +464,14 @@ static void prl_list_destroy_rcu(struct rcu_head *head)
 	return ok;
 }
 
+static void ipip6_destructor_free(struct net_device *dev)
+{
+	struct ip_tunnel *tunnel = netdev_priv(dev);
+
+	dst_cache_destroy(&tunnel->dst_cache);
+	free_percpu(dev->tstats);
+}
+
 static void ipip6_tunnel_uninit(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
@@ -477,6 +485,10 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
 	}
 	dst_cache_reset(&tunnel->dst_cache);
 	dev_put(dev);
+
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		ipip6_destructor_free(dev);
 }
 
 static int ipip6_err(struct sk_buff *skb, u32 info)
@@ -1329,10 +1341,7 @@ static bool ipip6_valid_ip_proto(u8 ipproto)
 
 static void ipip6_dev_free(struct net_device *dev)
 {
-	struct ip_tunnel *tunnel = netdev_priv(dev);
-
-	dst_cache_destroy(&tunnel->dst_cache);
-	free_percpu(dev->tstats);
+	ipip6_destructor_free(dev);
 	free_netdev(dev);
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 11/12] net: vlan: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (10 preceding siblings ...)
  2017-05-02 13:39 ` [PATCH net v4 10/12] net: sit: " gfree.wind
@ 2017-05-02 13:41 ` gfree.wind
  2017-05-02 14:17 ` [PATCH net v4 12/12] net: batman-adv: " gfree.wind
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02 13:41 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The vlan driver allocates some resources in its ndo_init func, and
free some of them in its destructor func. Then there is one memleak
that some errors happen after register_netdevice invokes the ndo_init
callback. Because only the ndo_uninit callback is invoked in the error
handler of register_netdevice, but destructor not.

Now create one new func vlan_destructor_free to free the mem in the
destructor, and ndo_uninit func also invokes it when fail to register
the vlan device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 net/8021q/vlan_dev.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index e97ab82..adcaa39 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -608,6 +608,14 @@ static int vlan_dev_init(struct net_device *dev)
 	return 0;
 }
 
+static void vlan_destructor_free(struct net_device *dev)
+{
+	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+
+	free_percpu(vlan->vlan_pcpu_stats);
+	vlan->vlan_pcpu_stats = NULL;
+}
+
 static void vlan_dev_uninit(struct net_device *dev)
 {
 	struct vlan_priority_tci_mapping *pm;
@@ -620,6 +628,10 @@ static void vlan_dev_uninit(struct net_device *dev)
 			kfree(pm);
 		}
 	}
+
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		vlan_destructor_free(dev);
 }
 
 static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
@@ -803,10 +815,7 @@ static int vlan_dev_get_iflink(const struct net_device *dev)
 
 static void vlan_dev_free(struct net_device *dev)
 {
-	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
-
-	free_percpu(vlan->vlan_pcpu_stats);
-	vlan->vlan_pcpu_stats = NULL;
+	vlan_destructor_free(dev);
 	free_netdev(dev);
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH net v4 12/12] net: batman-adv: Fix one possbile memleak when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (11 preceding siblings ...)
  2017-05-02 13:41 ` [PATCH net v4 11/12] net: vlan: " gfree.wind
@ 2017-05-02 14:17 ` gfree.wind
  2017-05-02 19:30 ` [PATCH net v4 00/12] Fix possbile memleaks " David Miller
  2017-05-07 22:25 ` David Miller
  14 siblings, 0 replies; 18+ messages in thread
From: gfree.wind @ 2017-05-02 14:17 UTC (permalink / raw)
  To: davem, jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji,
	kaber, steffen.klassert, herbert, netdev
  Cc: Gao Feng

From: Gao Feng <gfree.wind@foxmail.com>

The batman-adv allocates some resources in its ndo_init func, and free
them in its destructor func. Then there is one memleak that some errors
happen after register_netdevice invokes the ndo_init callback. Because
the destructor would not be invoked to free the resources.

Now create one new func batadv_destructor_free to free the mem in
the destructor, and add ndo_uninit func also invokes it when fail to
register the batman-adv device.

It's not only free all resources, but also follow the original desgin
that the resources are freed in the destructor normally after
register the device successfully.

Signed-off-by: Gao Feng <gfree.wind@foxmail.com>
---
 net/batman-adv/soft-interface.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index d042c99..626cbf6 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -878,6 +878,19 @@ static int batadv_softif_init_late(struct net_device *dev)
 	return ret;
 }
 
+static void batadv_destructor_free(struct net_device *dev)
+{
+	batadv_debugfs_del_meshif(dev);
+	batadv_mesh_free(dev);
+}
+
+static void batadv_softif_uninit(struct net_device *dev)
+{
+	/* dev is not registered, perform the free instead of destructor */
+	if (dev->reg_state == NETREG_UNINITIALIZED)
+		batadv_destructor_free(dev);
+}
+
 /**
  * batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface
  * @dev: batadv_soft_interface used as master interface
@@ -933,6 +946,7 @@ static int batadv_softif_slave_del(struct net_device *dev,
 
 static const struct net_device_ops batadv_netdev_ops = {
 	.ndo_init = batadv_softif_init_late,
+	.ndo_uninit = batadv_softif_uninit,
 	.ndo_open = batadv_interface_open,
 	.ndo_stop = batadv_interface_release,
 	.ndo_get_stats = batadv_interface_stats,
@@ -953,9 +967,7 @@ static int batadv_softif_slave_del(struct net_device *dev,
  */
 static void batadv_softif_free(struct net_device *dev)
 {
-	batadv_debugfs_del_meshif(dev);
-	batadv_mesh_free(dev);
-
+	batadv_destructor_free(dev);
 	/* some scheduled RCU callbacks need the bat_priv struct to accomplish
 	 * their tasks. Wait for them all to be finished before freeing the
 	 * netdev and its private data (bat_priv)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (12 preceding siblings ...)
  2017-05-02 14:17 ` [PATCH net v4 12/12] net: batman-adv: " gfree.wind
@ 2017-05-02 19:30 ` David Miller
  2017-05-03  0:33   ` Gao Feng
  2017-05-07 22:25 ` David Miller
  14 siblings, 1 reply; 18+ messages in thread
From: David Miller @ 2017-05-02 19:30 UTC (permalink / raw)
  To: gfree.wind
  Cc: jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji, kaber,
	steffen.klassert, herbert, netdev

From: gfree.wind@foxmail.com
Date: Tue,  2 May 2017 13:58:42 +0800

> These following drivers allocate kinds of resources in its ndo_init
> func, free some of them or all in the destructor func. Then there is
> one memleak that some errors happen after register_netdevice invokes
> the ndo_init callback. Because only the ndo_uninit callback is invoked
> in the error handler of register_netdevice, but destructor not.
> 
> In my original approach, I tried to free the resources in the newlink
> func when fail to register_netdevice, like destructor did except not
> free the net_dev. This method is not good when destructor is changed,
> and the memleak could be not fixed when there is no newlink callback.
> 
> Now create one new func used to free the resources in the destructor,
> and the ndo_uninit func also could invokes it when fail to register
> the net_device by comparing the dev->reg_state with NETREG_UNINITIALIZED.
> If there is no existing ndo_uninit, just add one.
> 
> This solution doesn't only make sure free all resources in any case,
> but also follows the original desgin that some resources could be kept
> until the destructor executes normally after register the device
> successfully.

I want to think about this some more.

It is really unfortunate that resources are allocated strictly from
the ndo_init() yet released in two different callbacks which are
invoked only in certain (different) situations.

Just the fact that we have to make an internal netdev state test
in the ndo_uninit callback to get this right is a big red flag
to me.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice
  2017-05-02 19:30 ` [PATCH net v4 00/12] Fix possbile memleaks " David Miller
@ 2017-05-03  0:33   ` Gao Feng
  0 siblings, 0 replies; 18+ messages in thread
From: Gao Feng @ 2017-05-03  0:33 UTC (permalink / raw)
  To: 'David Miller'
  Cc: jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji, kaber,
	steffen.klassert, herbert, netdev

Hi David

> From: David Miller [mailto:davem@davemloft.net]
> Sent: Wednesday, May 3, 2017 3:30 AM
> From: gfree.wind@foxmail.com
> Date: Tue,  2 May 2017 13:58:42 +0800
> 
[...]
> >
> > This solution doesn't only make sure free all resources in any case,
> > but also follows the original desgin that some resources could be kept
> > until the destructor executes normally after register the device
> > successfully.
> 
> I want to think about this some more.
> 
> It is really unfortunate that resources are allocated strictly from the
ndo_init()
> yet released in two different callbacks which are invoked only in certain
> (different) situations.
> 
> Just the fact that we have to make an internal netdev state test in the
> ndo_uninit callback to get this right is a big red flag to me.

Yes, I am very agree with you.
This fix is just like a workaround under current framework.

The root is that allocate in one spot, but free them at two spots.
It means all ndo_uninit need to handle this case if allocate some resource
and free them in the destructor.
It should be done by the framework.

I thought about if there was a better solution to fix it.
But I think it need to modify the framework of net_device, it seems not good
as a bug fix to net.git.

Best Regards
Feng

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice
  2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
                   ` (13 preceding siblings ...)
  2017-05-02 19:30 ` [PATCH net v4 00/12] Fix possbile memleaks " David Miller
@ 2017-05-07 22:25 ` David Miller
  2017-05-08  4:18   ` Gao Feng
  14 siblings, 1 reply; 18+ messages in thread
From: David Miller @ 2017-05-07 22:25 UTC (permalink / raw)
  To: gfree.wind
  Cc: jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji, kaber,
	steffen.klassert, herbert, netdev

From: gfree.wind@foxmail.com
Date: Tue,  2 May 2017 13:58:42 +0800

> These following drivers allocate kinds of resources in its ndo_init
> func, free some of them or all in the destructor func. Then there is
> one memleak that some errors happen after register_netdevice invokes
> the ndo_init callback. Because only the ndo_uninit callback is invoked
> in the error handler of register_netdevice, but destructor not.
> 
> In my original approach, I tried to free the resources in the
> newlink func when fail to register_netdevice, like destructor did
> except not free the net_dev. This method is not good when destructor
> is changed, and the memleak could be not fixed when there is no
> newlink callback.
> 
> Now create one new func used to free the resources in the
> destructor, and the ndo_uninit func also could invokes it when fail
> to register the net_device by comparing the dev->reg_state with
> NETREG_UNINITIALIZED.  If there is no existing ndo_uninit, just add
> one.
> 
> This solution doesn't only make sure free all resources in any case,
> but also follows the original desgin that some resources could be
> kept until the destructor executes normally after register the
> device successfully.

Device private teardown is in two stages for the following reason.
The issue is that netdev_ops->ndo_init() allocates two types of
resources.

One type is OK to release during destruction before the netdev refs
goes to zero.  This is what netdev_ops->ndo_uninit() is for.

The second type is for releasing things which are not safe to drop
until the very last netdev reference disappears.  This is what
netdev->destructor() is for.

If you look around there are hacks in place all over to try and deal
with this issue.  Basically, look for code that checks the return
value of register_netdev() and if an error is indicated it does
some local driver state freeing.  Bonding is one example.  It is
trying to deal with the problem this patch set is targetting.

What really needs to happen is we must divorce the logic of
dev->destructor() from free_netdev().

That way we can do the free_netdev in the unregister netdevice path
after calling netdev->destructor().

Then the only issue callers of register_netdevice() need to be aware
of is that if an error is returned, that caller must call
free_netdev().  Which has been the case for decades.

So I would fix this as follows:

1) Rename netdev->destructor() into "netdev->priv_destructor()"  It
   performs all post ndo_ops->ndo_uninit() cleanups, _except_
   free_netdev().  Update all drivers with netdev->destructor().

2) Add a boolean state to netdev, which indicates if free_netdev()
   should be performed after netdev->priv_destructor() during
   unregister.

That provides all of the flexibility necessary to fix this bug in
the core.

In register_netdevice() if something after ndo_ops->ndo_init()
succeeeds, we invoke _both_ ndo_ops->ndo_uninit() and
netdev->priv_destructor().  We do not look at the netdev "needs
free_netdev()" boolean.

In netdev_run_todo(), where we have the one and only
netdev->destructor() call, change it to:

	if (dev->priv_destructor)
		dev->priv_destructor(dev);
	if (dev->needs_free_netdev)
		free_netdev(dev);

That fixes the bug in all cases.  And makes the purpose and logic
extremely clear.  Also, no internal state tests leak into the
drivers.

Finally, drivers that try to cover up this issue, such as bonding,
need to be changed to no try and free up device private state if
their invocation of register_netdevice() fails.

Thanks.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice
  2017-05-07 22:25 ` David Miller
@ 2017-05-08  4:18   ` Gao Feng
  0 siblings, 0 replies; 18+ messages in thread
From: Gao Feng @ 2017-05-08  4:18 UTC (permalink / raw)
  To: 'David Miller'
  Cc: jiri, mareklindner, sw, a, kuznet, jmorris, yoshfuji, kaber,
	steffen.klassert, herbert, netdev

Hi David,

> From: David Miller [mailto:davem@davemloft.net]
> From: gfree.wind@foxmail.com
> Date: Tue,  2 May 2017 13:58:42 +0800
> 
> > These following drivers allocate kinds of resources in its ndo_init
> > func, free some of them or all in the destructor func. Then there is
> > one memleak that some errors happen after register_netdevice invokes
> > the ndo_init callback. Because only the ndo_uninit callback is invoked
> > in the error handler of register_netdevice, but destructor not.
> >
> > In my original approach, I tried to free the resources in the newlink
> > func when fail to register_netdevice, like destructor did except not
> > free the net_dev. This method is not good when destructor is changed,
> > and the memleak could be not fixed when there is no newlink callback.
> >
> > Now create one new func used to free the resources in the destructor,
> > and the ndo_uninit func also could invokes it when fail to register
> > the net_device by comparing the dev->reg_state with
> > NETREG_UNINITIALIZED.  If there is no existing ndo_uninit, just add
> > one.
> >
> > This solution doesn't only make sure free all resources in any case,
> > but also follows the original desgin that some resources could be kept
> > until the destructor executes normally after register the device
> > successfully.
> 
> Device private teardown is in two stages for the following reason.
> The issue is that netdev_ops->ndo_init() allocates two types of resources.
> 
> One type is OK to release during destruction before the netdev refs goes
to
> zero.  This is what netdev_ops->ndo_uninit() is for.
> 
> The second type is for releasing things which are not safe to drop until
the very
> last netdev reference disappears.  This is what
> netdev->destructor() is for.
> 
> If you look around there are hacks in place all over to try and deal with
this
> issue.  Basically, look for code that checks the return value of
> register_netdev() and if an error is indicated it does some local driver
state
> freeing.  Bonding is one example.  It is trying to deal with the problem
this
> patch set is targetting.

Yes. When I was fixing this bug, I had found the bond had deal with this
issue, frees the resources by itself.

> 
> What really needs to happen is we must divorce the logic of
> dev->destructor() from free_netdev().
> 
> That way we can do the free_netdev in the unregister netdevice path after
> calling netdev->destructor().
> 
> Then the only issue callers of register_netdevice() need to be aware of is
that if
> an error is returned, that caller must call free_netdev().  Which has been
the
> case for decades.
> 
> So I would fix this as follows:
> 
> 1) Rename netdev->destructor() into "netdev->priv_destructor()"  It
>    performs all post ndo_ops->ndo_uninit() cleanups, _except_
>    free_netdev().  Update all drivers with netdev->destructor().
> 
> 2) Add a boolean state to netdev, which indicates if free_netdev()
>    should be performed after netdev->priv_destructor() during
>    unregister.
> 
> That provides all of the flexibility necessary to fix this bug in the
core.
> 
> In register_netdevice() if something after ndo_ops->ndo_init() succeeeds,
we
> invoke _both_ ndo_ops->ndo_uninit() and
> netdev->priv_destructor().  We do not look at the netdev "needs
> free_netdev()" boolean.
> 
> In netdev_run_todo(), where we have the one and only
> netdev->destructor() call, change it to:
> 
> 	if (dev->priv_destructor)
> 		dev->priv_destructor(dev);
> 	if (dev->needs_free_netdev)
> 		free_netdev(dev);
> 
> That fixes the bug in all cases.  And makes the purpose and logic
extremely
> clear.  Also, no internal state tests leak into the drivers.
> 
> Finally, drivers that try to cover up this issue, such as bonding, need to
be
> changed to no try and free up device private state if their invocation of
> register_netdevice() fails.
> 
> Thanks.

Ok. It is better to fix it by changing the framework of net_dev.
I was afraid that I would bring other bugs if I changed it.
Because it would affect too many codes.

I would like to see you fix it by yourself.

Best Regards
Feng

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2017-05-08  4:19 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-02  5:58 [PATCH net v4 00/12] Fix possbile memleaks when fail to register_netdevice gfree.wind
2017-05-02  5:58 ` [PATCH net v4 01/12] driver: dummy: Fix one possbile memleak " gfree.wind
2017-05-02  5:58 ` [PATCH net v4 02/12] driver: ifb: " gfree.wind
2017-05-02  5:58 ` [PATCH net v4 03/12] driver: loopback: " gfree.wind
2017-05-02  5:58 ` [PATCH net v4 04/12] driver: team: " gfree.wind
2017-05-02  5:58 ` [PATCH net v4 05/12] driver: veth: " gfree.wind
2017-05-02  5:58 ` [PATCH net v4 06/12] net: ip6_gre: " gfree.wind
2017-05-02  6:59 ` [PATCH net v4 07/12] ip6_tunnel: " gfree.wind
2017-05-02 11:10 ` [PATCH net v4 00/12] Fix possbile memleaks " Gao Feng
2017-05-02 13:34 ` [PATCH net v4 08/12] net: ip6_vti: Fix one possbile memleak " gfree.wind
2017-05-02 13:37 ` [PATCH net v4 09/12] net: ip_tunnel: " gfree.wind
2017-05-02 13:39 ` [PATCH net v4 10/12] net: sit: " gfree.wind
2017-05-02 13:41 ` [PATCH net v4 11/12] net: vlan: " gfree.wind
2017-05-02 14:17 ` [PATCH net v4 12/12] net: batman-adv: " gfree.wind
2017-05-02 19:30 ` [PATCH net v4 00/12] Fix possbile memleaks " David Miller
2017-05-03  0:33   ` Gao Feng
2017-05-07 22:25 ` David Miller
2017-05-08  4:18   ` Gao Feng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.