[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <m1wr5d3cyv.fsf@fess.ebiederm.org>
Date: Tue, 17 Apr 2012 21:01:28 -0700
From: ebiederm@...ssion.com (Eric W. Biederman)
To: Julian Anastasov <ja@....bg>
Cc: netdev@...r.kernel.org
Subject: Re: [PATCH] netns: do not leak net_generic data on failed init
Julian Anastasov <ja@....bg> writes:
> ops_init should free the net_generic data on
> init failure and __register_pernet_operations should not
> call ops_free when NET_NS is not enabled.
The subject is good.
There is most definitely a leak with us not freeing the net_generic data
on ops_init failure. Having ops_init just take care of it seems like
the logical place as it makes for simple analysis.
The bit about __register_pernet_operations should not call ops_free when
NET_NS is not enabled is a bad comment. We just need to move the
ops_free into ops_init on failure, which is what your patch does.
Without your patch the only caller of ops_init that doesn't leak today
is __register_pernet_operations in !CONFIG_NET_NS, precisely because
it does that ops_free.
Now all of that said I have just read through everything and
patch cleanly fixes a rare but real memory leak, and leaves
the code in better state then it is today.
David please apply this patch.
Reviewed-by: "Eric W. Biederman" <ebiederm@...ssion.com>
> Signed-off-by: Julian Anastasov <ja@....bg>
> ---
> net/core/net_namespace.c | 33 ++++++++++++++++++---------------
> 1 files changed, 18 insertions(+), 15 deletions(-)
>
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index 0e950fd..31a5ae5 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -83,21 +83,29 @@ assign:
>
> static int ops_init(const struct pernet_operations *ops, struct net *net)
> {
> - int err;
> + int err = -ENOMEM;
> + void *data = NULL;
> +
> if (ops->id && ops->size) {
> - void *data = kzalloc(ops->size, GFP_KERNEL);
> + data = kzalloc(ops->size, GFP_KERNEL);
> if (!data)
> - return -ENOMEM;
> + goto out;
>
> err = net_assign_generic(net, *ops->id, data);
> - if (err) {
> - kfree(data);
> - return err;
> - }
> + if (err)
> + goto cleanup;
> }
> + err = 0;
> if (ops->init)
> - return ops->init(net);
> - return 0;
> + err = ops->init(net);
> + if (!err)
> + return 0;
> +
> +cleanup:
> + kfree(data);
> +
> +out:
> + return err;
> }
>
> static void ops_free(const struct pernet_operations *ops, struct net *net)
> @@ -448,12 +456,7 @@ static void __unregister_pernet_operations(struct pernet_operations *ops)
> static int __register_pernet_operations(struct list_head *list,
> struct pernet_operations *ops)
> {
> - int err = 0;
> - err = ops_init(ops, &init_net);
> - if (err)
> - ops_free(ops, &init_net);
> - return err;
> -
> + return ops_init(ops, &init_net);
> }
>
> static void __unregister_pernet_operations(struct pernet_operations *ops)
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists