| From a028fe3db3df8800408ee09194dab72ea68369c9 Mon Sep 17 00:00:00 2001 |
| From: Julian Anastasov <ja@ssi.bg> |
| Date: Mon, 16 Apr 2012 04:43:15 +0000 |
| Subject: [PATCH 23/28] netns: do not leak net_generic data on failed init |
| |
| |
| From: Julian Anastasov <ja@ssi.bg> |
| |
| [ Upstream commit b922934d017f1cc831b017913ed7d1a56c558b43 ] |
| |
| 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. |
| |
| Signed-off-by: Julian Anastasov <ja@ssi.bg> |
| Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/core/net_namespace.c | 33 ++++++++++++++++++--------------- |
| 1 file changed, 18 insertions(+), 15 deletions(-) |
| |
| --- 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_operatio |
| 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) |