aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-01-10 10:12:01 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2013-01-12 08:12:36 -0500
commit1e47ee8367babe6a5e8adf44a714c7086657b87e (patch)
tree09596b40accfa9adcf21f7b0a26f99cee7d4e0e7
parent4610476d89d53714ca94aae081fa035908bc137a (diff)
netfilter: nf_conntrack: fix BUG_ON while removing nf_conntrack with netns
canqun zhang reported that we're hitting BUG_ON in the nf_conntrack_destroy path when calling kfree_skb while rmmod'ing the nf_conntrack module. Currently, the nf_ct_destroy hook is being set to NULL in the destroy path of conntrack.init_net. However, this is a problem since init_net may be destroyed before any other existing netns (we cannot assume any specific ordering while releasing existing netns according to what I read in recent emails). Thanks to Gao feng for initial patch to address this issue. Reported-by: canqun zhang <canqunzhang@gmail.com> Acked-by: Gao feng <gaofeng@cn.fujitsu.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/net/netfilter/nf_conntrack_core.h2
-rw-r--r--net/netfilter/nf_conntrack_core.c9
-rw-r--r--net/netfilter/nf_conntrack_standalone.c1
3 files changed, 8 insertions, 4 deletions
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index d8f5b9f52169..e98aeb3da033 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -31,6 +31,8 @@ extern void nf_conntrack_cleanup(struct net *net);
31extern int nf_conntrack_proto_init(struct net *net); 31extern int nf_conntrack_proto_init(struct net *net);
32extern void nf_conntrack_proto_fini(struct net *net); 32extern void nf_conntrack_proto_fini(struct net *net);
33 33
34extern void nf_conntrack_cleanup_end(void);
35
34extern bool 36extern bool
35nf_ct_get_tuple(const struct sk_buff *skb, 37nf_ct_get_tuple(const struct sk_buff *skb,
36 unsigned int nhoff, 38 unsigned int nhoff,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 016d95ead930..e4a0c4fb3a7c 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1376,11 +1376,12 @@ void nf_conntrack_cleanup(struct net *net)
1376 synchronize_net(); 1376 synchronize_net();
1377 nf_conntrack_proto_fini(net); 1377 nf_conntrack_proto_fini(net);
1378 nf_conntrack_cleanup_net(net); 1378 nf_conntrack_cleanup_net(net);
1379}
1379 1380
1380 if (net_eq(net, &init_net)) { 1381void nf_conntrack_cleanup_end(void)
1381 RCU_INIT_POINTER(nf_ct_destroy, NULL); 1382{
1382 nf_conntrack_cleanup_init_net(); 1383 RCU_INIT_POINTER(nf_ct_destroy, NULL);
1383 } 1384 nf_conntrack_cleanup_init_net();
1384} 1385}
1385 1386
1386void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls) 1387void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 363285d544a1..e7185c684816 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -575,6 +575,7 @@ static int __init nf_conntrack_standalone_init(void)
575static void __exit nf_conntrack_standalone_fini(void) 575static void __exit nf_conntrack_standalone_fini(void)
576{ 576{
577 unregister_pernet_subsys(&nf_conntrack_net_ops); 577 unregister_pernet_subsys(&nf_conntrack_net_ops);
578 nf_conntrack_cleanup_end();
578} 579}
579 580
580module_init(nf_conntrack_standalone_init); 581module_init(nf_conntrack_standalone_init);