summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly E. Lavrov <lve@guap.ru>2012-12-24 13:55:20 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2012-12-26 18:14:48 +0100
commit665e205c16c1f902ac6763b8ce8a0a3a1dcefe59 (patch)
treedf165b4009ded7206cf357d75a62f042bbb3c910
parentnetfilter: xt_hashlimit: fix race that results in duplicated entries (diff)
downloadlinux-665e205c16c1f902ac6763b8ce8a0a3a1dcefe59.tar.xz
linux-665e205c16c1f902ac6763b8ce8a0a3a1dcefe59.zip
netfilter: xt_recent: fix namespace destroy path
recent_net_exit() is called before recent_mt_destroy() in the destroy path of network namespaces. Make sure there are no entries in the parent proc entry xt_recent before removing it. Signed-off-by: Vitaly E. Lavrov <lve@guap.ru> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/xt_recent.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index 4635c9b00459..dab053e2a1a2 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -431,7 +431,8 @@ static void recent_mt_destroy(const struct xt_mtdtor_param *par)
list_del(&t->list);
spin_unlock_bh(&recent_lock);
#ifdef CONFIG_PROC_FS
- remove_proc_entry(t->name, recent_net->xt_recent);
+ if (recent_net->xt_recent != NULL)
+ remove_proc_entry(t->name, recent_net->xt_recent);
#endif
recent_table_flush(t);
kfree(t);
@@ -615,6 +616,20 @@ static int __net_init recent_proc_net_init(struct net *net)
static void __net_exit recent_proc_net_exit(struct net *net)
{
+ struct recent_net *recent_net = recent_pernet(net);
+ struct recent_table *t;
+
+ /* recent_net_exit() is called before recent_mt_destroy(). Make sure
+ * that the parent xt_recent proc entry is is empty before trying to
+ * remove it.
+ */
+ spin_lock_bh(&recent_lock);
+ list_for_each_entry(t, &recent_net->tables, list)
+ remove_proc_entry(t->name, recent_net->xt_recent);
+
+ recent_net->xt_recent = NULL;
+ spin_unlock_bh(&recent_lock);
+
proc_net_remove(net, "xt_recent");
}
#else
@@ -638,9 +653,6 @@ static int __net_init recent_net_init(struct net *net)
static void __net_exit recent_net_exit(struct net *net)
{
- struct recent_net *recent_net = recent_pernet(net);
-
- BUG_ON(!list_empty(&recent_net->tables));
recent_proc_net_exit(net);
}