All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Vitaly E. Lavrov" <lve@guap.ru>
To: netfilter-devel@vger.kernel.org
Subject: [PATCH] xt_hashlimit fix BUG()
Date: Tue, 11 Dec 2012 23:32:21 +0400	[thread overview]
Message-ID: <50C78A45.4040901@guap.ru> (raw)

[-- Attachment #1: Type: text/plain, Size: 2781 bytes --]

The following patch fixes a bug in xt_hashlimit.
Bug appears at the end of work the networks namespace, provided that the 
tables (filter/mangle/raw) have rule  with xt_hashlimit.
The error occurs because the __net_exit hashlimit_net_exit() is executed 
before the tables are cleared.
Change this order of calls is impossible, since tables must be 
registered earlier than extensions.
Bug exists in all versions of the kernel since 2.6.35

Cleaning tables before completing the network namespace can be used as a 
workaround.

Idea of the patch that if the files are deleted from the directory 
/proc/net/ip[6]t_hashlimit/" procedure XXXXX, then a flag is set "clean".
If cleaning the tables occurs later and the flag "clean" is set, then 
the delete files is skipped.

Patch for kernel 3.4.22

Signed-off-by: Vitaly Lavrov lve@guap.ru

---
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 2195eb0..5416185 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -46,6 +46,7 @@ struct hashlimit_net {
         struct hlist_head       htables;
         struct proc_dir_entry   *ipt_hashlimit;
         struct proc_dir_entry   *ip6t_hashlimit;
+       int                     clean;
  };

  static int hashlimit_net_id;
@@ -319,7 +320,8 @@ static void htable_destroy(struct 
xt_hashlimit_htable *hinfo)
                 parent = hashlimit_net->ipt_hashlimit;
         else
                 parent = hashlimit_net->ip6t_hashlimit;
-       remove_proc_entry(hinfo->pde->name, parent);
+       if(!hashlimit_net->clean)
+               remove_proc_entry(hinfo->pde->name, parent);
         htable_selective_cleanup(hinfo, select_all);
         vfree(hinfo);
  }
@@ -784,6 +786,7 @@ static int __net_init hashlimit_net_init(struct net 
*net)
  {
         struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);

+       hashlimit_net->clean = 0;
         INIT_HLIST_HEAD(&hashlimit_net->htables);
         return hashlimit_proc_net_init(net);
  }
@@ -791,8 +794,19 @@ static int __net_init hashlimit_net_init(struct net 
*net)
  static void __net_exit hashlimit_net_exit(struct net *net)
  {
         struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
+       struct xt_hashlimit_htable *hinfo;
+       struct hlist_node *pos;
+       struct proc_dir_entry *pde;
+
+       mutex_lock(&hashlimit_mutex);
+       hashlimit_net->clean = 1;
+       pde = hashlimit_net->ipt_hashlimit;
+       if(!pde) pde = hashlimit_net->ip6t_hashlimit;
+       hlist_for_each_entry(hinfo, pos, &hashlimit_net->htables, node) {
+               remove_proc_entry(hinfo->pde->name,pde);
+       }
+       mutex_unlock(&hashlimit_mutex);

-       BUG_ON(!hlist_empty(&hashlimit_net->htables));
         hashlimit_proc_net_exit(net);
  }
--

[-- Attachment #2: xt_hashlimit.c.patch --]
[-- Type: text/plain, Size: 1682 bytes --]

diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 2195eb0..5416185 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -46,6 +46,7 @@ struct hashlimit_net {
 	struct hlist_head	htables;
 	struct proc_dir_entry	*ipt_hashlimit;
 	struct proc_dir_entry	*ip6t_hashlimit;
+	int			clean;
 };
 
 static int hashlimit_net_id;
@@ -319,7 +320,8 @@ static void htable_destroy(struct xt_hashlimit_htable *hinfo)
 		parent = hashlimit_net->ipt_hashlimit;
 	else
 		parent = hashlimit_net->ip6t_hashlimit;
-	remove_proc_entry(hinfo->pde->name, parent);
+	if(!hashlimit_net->clean)
+		remove_proc_entry(hinfo->pde->name, parent);
 	htable_selective_cleanup(hinfo, select_all);
 	vfree(hinfo);
 }
@@ -784,6 +786,7 @@ static int __net_init hashlimit_net_init(struct net *net)
 {
 	struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
 
+	hashlimit_net->clean = 0;
 	INIT_HLIST_HEAD(&hashlimit_net->htables);
 	return hashlimit_proc_net_init(net);
 }
@@ -791,8 +794,19 @@ static int __net_init hashlimit_net_init(struct net *net)
 static void __net_exit hashlimit_net_exit(struct net *net)
 {
 	struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
+	struct xt_hashlimit_htable *hinfo;
+	struct hlist_node *pos;
+	struct proc_dir_entry *pde;
+
+	mutex_lock(&hashlimit_mutex);
+	hashlimit_net->clean = 1;
+	pde = hashlimit_net->ipt_hashlimit;
+	if(!pde) pde = hashlimit_net->ip6t_hashlimit;
+	hlist_for_each_entry(hinfo, pos, &hashlimit_net->htables, node) {
+		remove_proc_entry(hinfo->pde->name,pde);
+	}
+	mutex_unlock(&hashlimit_mutex);
 
-	BUG_ON(!hlist_empty(&hashlimit_net->htables));
 	hashlimit_proc_net_exit(net);
 }
 

                 reply	other threads:[~2012-12-11 19:32 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=50C78A45.4040901@guap.ru \
    --to=lve@guap.ru \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.