All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: "David S. Miller" <davem@davemloft.net>
Cc: Netfilter Development Mailinglist <netfilter-devel@lists.netfilter.org>
Subject: [NETFILTER 2.4 1/1]: Handle NAT module load race
Date: Wed, 07 Sep 2005 03:06:04 +0200	[thread overview]
Message-ID: <431E3CFC.7060303@trash.net> (raw)

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

This is the backport of the NAT race fix which prevents
a crash with CONFIG_NETFILTER_DEBUG when conntracks
are established before the nat module is loaded.

[-- Attachment #2: 01.diff --]
[-- Type: text/x-patch, Size: 3636 bytes --]

[NETFILTER]: Handle NAT module load race

When the NAT module is loaded when connections are already confirmed
it must not change their tuples anymore. This is especially important
with CONFIG_NETFILTER_DEBUG, the netfilter listhelp functions will
refuse to remove an entry from a list when it can not be found on
the list, so when a changed tuple hashes to a new bucket the entry
is kept in the list until and after the conntrack is freed.

Allocate the exact conntrack tuple for NAT for already confirmed
connections or drop them if that fails.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 6fa066570cf415817cd317d3f968b769a3b8cce6
tree a7ce08e43fc79d31c292a300128235565dec18f9
parent 7cbdf66daf8a9b9aa9b1e2bc2c1404511414c5c6
author Patrick McHardy <kaber@trash.net> Sun, 04 Sep 2005 23:18:14 +0200
committer Patrick McHardy <kaber@trash.net> Sun, 04 Sep 2005 23:18:14 +0200

 include/linux/netfilter_ipv4/ip_nat_rule.h |    5 +++++
 net/ipv4/netfilter/ip_nat_rule.c           |   21 +++++++++++++++++++++
 net/ipv4/netfilter/ip_nat_standalone.c     |    8 ++++++--
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/include/linux/netfilter_ipv4/ip_nat_rule.h b/include/linux/netfilter_ipv4/ip_nat_rule.h
--- a/include/linux/netfilter_ipv4/ip_nat_rule.h
+++ b/include/linux/netfilter_ipv4/ip_nat_rule.h
@@ -19,5 +19,10 @@ extern unsigned int
 alloc_null_binding(struct ip_conntrack *conntrack,
 		   struct ip_nat_info *info,
 		   unsigned int hooknum);
+
+extern unsigned int
+alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
+			     struct ip_nat_info *info,
+			     unsigned int hooknum);
 #endif
 #endif /* _IP_NAT_RULE_H */
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -241,6 +241,27 @@ alloc_null_binding(struct ip_conntrack *
 	return ip_nat_setup_info(conntrack, &mr, hooknum);
 }
 
+unsigned int
+alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
+                             struct ip_nat_info *info,
+                             unsigned int hooknum)
+{
+	u_int32_t ip
+		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+		   ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
+		   : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
+	u_int16_t all
+		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+		   ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
+		   : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
+	struct ip_nat_multi_range mr
+		= { 1, { { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } } } };
+
+	DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+	       conntrack, NIPQUAD(ip));
+	return ip_nat_setup_info(conntrack, &mr, hooknum);
+}
+
 int ip_nat_rule_find(struct sk_buff **pskb,
 		     unsigned int hooknum,
 		     const struct net_device *in,
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -123,8 +123,12 @@ ip_nat_fn(unsigned int hooknum,
 				ret = call_expect(master_ct(ct), pskb, 
 						  hooknum, ct, info);
 			} else {
-				/* LOCAL_IN hook doesn't have a chain!  */
-				if (hooknum == NF_IP_LOCAL_IN)
+				if (unlikely(is_confirmed(ct)))
+					/* NAT module was loaded late */
+					ret = alloc_null_binding_confirmed(ct, info,
+		        		                                   hooknum);
+				else if (hooknum == NF_IP_LOCAL_IN)
+					/* LOCAL_IN hook doesn't have a chain */
 					ret = alloc_null_binding(ct, info,
 								 hooknum);
 				else

             reply	other threads:[~2005-09-07  1:06 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-07  1:06 Patrick McHardy [this message]
2005-09-07  3:01 ` [NETFILTER 2.4 1/1]: Handle NAT module load race David S. Miller

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=431E3CFC.7060303@trash.net \
    --to=kaber@trash.net \
    --cc=davem@davemloft.net \
    --cc=netfilter-devel@lists.netfilter.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.