List Info

Thread: Netfilter fixes




Netfilter fixes
user name
2006-12-12 08:06:18
Hi Dave,

following are a few netfilter fixes (mostly conntrack
related), a patch to unify
the iptables compat and non-compat verification code and Al
Viro's iptables loop
check optimization with similar changes to ip6_tables and
arp_tables.

Please apply or pull from http:/
/people.netfilter.org/~kaber/nf-2.6.git/, thanks.


 include/net/netfilter/nf_conntrack_compat.h |   10 +
 net/ipv4/netfilter/Kconfig                  |    2 
 net/ipv4/netfilter/arp_tables.c             |    5 
 net/ipv4/netfilter/ip_tables.c              |  181
++++++++++++----------------
 net/ipv4/netfilter/ipt_CLUSTERIP.c          |    8 +
 net/ipv6/netfilter/ip6_tables.c             |    5 
 net/netfilter/Kconfig                       |    2 
 net/netfilter/xt_CONNMARK.c                 |   14 ++
 net/netfilter/xt_CONNSECMARK.c              |   14 ++
 net/netfilter/xt_connbytes.c                |   14 ++
 net/netfilter/xt_connmark.c                 |    7 -
 net/netfilter/xt_conntrack.c                |    8 -
 net/netfilter/xt_helper.c                   |    8 -
 net/netfilter/xt_state.c                    |    7 -
 14 files changed, 154 insertions(+), 131 deletions(-)

Al Viro:
      [NETFILTER]: {ip,ip6,arp}_tables: fix exponential
worst-case search for loops

Dmitry Mishin:
      [NETFILTER]: ip_tables: ipt and ipt_compat checks
unification

Patrick McHardy:
      [NETFILTER]: Fix INET=n linking error

Yasuyuki Kozakai:
      [NETFILTER]: nf_nat: fix NF_NAT dependency
      [NETFILTER]: x_tables: error if ip_conntrack is asked
to handle IPv6 packets
      [NETFILTER]: x_tables: add missing try to load
conntrack from match/targets

Fix INET=n linking error
user name
2006-12-12 08:06:19
[NETFILTER]: Fix INET=n linking error

Building with INET=n results in

WARNING: "ip_route_output_key"
[net/netfilter/nf_conntrack_h323.ko] undefined!

The entire code in net/netfilter is only used for IPv4/IPv6
currently, so
let it depend on INET.

Noticed by Toralf Förster <toralf.foerstergmx.de>.

Signed-off-by: Patrick McHardy <kabertrash.net>

---
commit 61ca98ed893d16bccb077bb88496d1e24b8604b2
tree 3adad9d96f832d98af105010eb3aaed0c9a83338
parent e63abb7bc148c5410f48496f8c339956947a1afb
author Patrick McHardy <kabertrash.net> Tue, 12 Dec
2006 08:50:36 +0100
committer Patrick McHardy <kabertrash.net> Tue, 12 Dec
2006 08:50:36 +0100

 net/netfilter/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3a66878..1b853c3 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
 -1,5
+1,5 
 menu "Core Netfilter Configuration"
-	depends on NET && NETFILTER
+	depends on NET && INET && NETFILTER
 
 config NETFILTER_NETLINK
        tristate "Netfilter netlink interface"

nf_nat: fix NF_NAT dependency
user name
2006-12-12 08:06:21
[NETFILTER]: nf_nat: fix NF_NAT dependency

NF_NAT depends on NF_CONNTRACK_IPV4, not NF_CONNTRACK.

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakaitoshiba.co.jp>
Signed-off-by: Patrick McHardy <kabertrash.net>

---
commit bc5ca5410c8fa8930ea4cf55ae034e163cb02b76
tree d7ab6180d2a687ff2edd5478d9bc1f276262321f
parent 61ca98ed893d16bccb077bb88496d1e24b8604b2
author Yasuyuki Kozakai <yasuyuki.kozakaitoshiba.co.jp> Tue, 12 Dec 2006 08:50:38 +0100
committer Patrick McHardy <kabertrash.net> Tue, 12 Dec
2006 08:50:38 +0100

 net/ipv4/netfilter/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/ipv4/netfilter/Kconfig
b/net/ipv4/netfilter/Kconfig
index 363df99..f6026d4 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
 -401,7
+401,7  config IP_NF_NAT
 # NAT + specific targets: nf_conntrack
 config NF_NAT
 	tristate "Full NAT"
-	depends on IP_NF_IPTABLES && NF_CONNTRACK
+	depends on IP_NF_IPTABLES && NF_CONNTRACK_IPV4
 	help
 	  The Full NAT option allows masquerading, port forwarding
and other
 	  forms of full Network Address Port Translation.  It is
controlled by

x_tables: error if ip_conntrack is asked to handle IPv6 packets
user name
2006-12-12 08:06:22
[NETFILTER]: x_tables: error if ip_conntrack is asked to
handle IPv6 packets

To do that, this makes nf_ct_l3proto_try_module_{get,put}
compatible
functions. As a result we can remove '#ifdef' surrounds and
direct call of
need_conntrack().

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakaitoshiba.co.jp>
Signed-off-by: Patrick McHardy <kabertrash.net>

---
commit 806a57fff01366038e04747ea75adf2c7c5db09f
tree 70890f4a68f8422b0daaf7e20b5ba23e3afdf1e7
parent bc5ca5410c8fa8930ea4cf55ae034e163cb02b76
author Yasuyuki Kozakai <yasuyuki.kozakaitoshiba.co.jp> Tue, 12 Dec 2006 08:50:42 +0100
committer Patrick McHardy <kabertrash.net> Tue, 12 Dec
2006 08:50:42 +0100

 include/net/netfilter/nf_conntrack_compat.h |   10
++++++++++
 net/netfilter/xt_connmark.c                 |    7 +------
 net/netfilter/xt_conntrack.c                |    8 ++------
 net/netfilter/xt_helper.c                   |    8 ++------
 net/netfilter/xt_state.c                    |    7 +------
 5 files changed, 16 insertions(+), 24 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_compat.h
b/include/net/netfilter/nf_conntrack_compat.h
index f1b1482..b9ce5c8 100644
--- a/include/net/netfilter/nf_conntrack_compat.h
+++ b/include/net/netfilter/nf_conntrack_compat.h
 -64,6
+64,16  static inline int nf_ct_get_ctinfo(const
 	return (ct != NULL);
 }
 
+static inline int nf_ct_l3proto_try_module_get(unsigned
short l3proto)
+{
+	need_conntrack();
+	return l3proto == PF_INET ? 0 : -1;
+}
+
+static inline void nf_ct_l3proto_module_put(unsigned short
l3proto)
+{
+}
+
 #else /* CONFIG_IP_NF_CONNTRACK */
 
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
diff --git a/net/netfilter/xt_connmark.c
b/net/netfilter/xt_connmark.c
index a8f0305..36c2def 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
 -63,22
+63,18  checkentry(const char *tablename,
 		printk(KERN_WARNING "connmark: only support 32bit
markn");
 		return 0;
 	}
-#if defined(CONFIG_NF_CONNTRACK) ||
defined(CONFIG_NF_CONNTRACK_MODULE)
 	if (nf_ct_l3proto_try_module_get(match->family) < 0)
{
-		printk(KERN_WARNING "can't load nf_conntrack support
for "
+		printk(KERN_WARNING "can't load conntrack support
for "
 				    "proto=%dn", match->family);
 		return 0;
 	}
-#endif
 	return 1;
 }
 
 static void
 destroy(const struct xt_match *match, void *matchinfo)
 {
-#if defined(CONFIG_NF_CONNTRACK) ||
defined(CONFIG_NF_CONNTRACK_MODULE)
 	nf_ct_l3proto_module_put(match->family);
-#endif
 }
 
 #ifdef CONFIG_COMPAT
 -140,7
+136,6  #endif
 
 static int __init xt_connmark_init(void)
 {
-	need_conntrack();
 	return xt_register_matches(xt_connmark_match,
 				   ARRAY_SIZE(xt_connmark_match));
 }
diff --git a/net/netfilter/xt_conntrack.c
b/net/netfilter/xt_conntrack.c
index 0ea501a..3dc2357 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
 -20,6
+20,7  #endif
 
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_conntrack.h>
+#include <net/netfilter/nf_conntrack_compat.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Marc Boucher <marcmbsi.ca>");
 -228,21
+229,17  checkentry(const char *tablename,
 	   void *matchinfo,
 	   unsigned int hook_mask)
 {
-#if defined(CONFIG_NF_CONNTRACK) ||
defined(CONFIG_NF_CONNTRACK_MODULE)
 	if (nf_ct_l3proto_try_module_get(match->family) < 0)
{
-		printk(KERN_WARNING "can't load nf_conntrack support
for "
+		printk(KERN_WARNING "can't load conntrack support
for "
 				    "proto=%dn", match->family);
 		return 0;
 	}
-#endif
 	return 1;
 }
 
 static void destroy(const struct xt_match *match, void
*matchinfo)
 {
-#if defined(CONFIG_NF_CONNTRACK) ||
defined(CONFIG_NF_CONNTRACK_MODULE)
 	nf_ct_l3proto_module_put(match->family);
-#endif
 }
 
 static struct xt_match conntrack_match = {
 -257,7
+254,6  static struct xt_match conntrack_match =
 
 static int __init xt_conntrack_init(void)
 {
-	need_conntrack();
 	return xt_register_match(&conntrack_match);
 }
 
diff --git a/net/netfilter/xt_helper.c
b/net/netfilter/xt_helper.c
index 5d7818b..04bc32b 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
 -24,6
+24,7  #include <net/netfilter/nf_conntrack_hel
 #endif
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_helper.h>
+#include <net/netfilter/nf_conntrack_compat.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Martin Josefsson <gandalfnetfilter.org>");
 -143,13
+144,11  static int check(const char *tablename,
 {
 	struct xt_helper_info *info = matchinfo;
 
-#if defined(CONFIG_NF_CONNTRACK) ||
defined(CONFIG_NF_CONNTRACK_MODULE)
 	if (nf_ct_l3proto_try_module_get(match->family) < 0)
{
-		printk(KERN_WARNING "can't load nf_conntrack support
for "
+		printk(KERN_WARNING "can't load conntrack support
for "
 				    "proto=%dn", match->family);
 		return 0;
 	}
-#endif
 	info->name[29] = '';
 	return 1;
 }
 -157,9
+156,7  #endif
 static void
 destroy(const struct xt_match *match, void *matchinfo)
 {
-#if defined(CONFIG_NF_CONNTRACK) ||
defined(CONFIG_NF_CONNTRACK_MODULE)
 	nf_ct_l3proto_module_put(match->family);
-#endif
 }
 
 static struct xt_match xt_helper_match[] = {
 -185,7
+182,6  static struct xt_match xt_helper_match[]
 
 static int __init xt_helper_init(void)
 {
-	need_conntrack();
 	return xt_register_matches(xt_helper_match,
 				   ARRAY_SIZE(xt_helper_match));
 }
diff --git a/net/netfilter/xt_state.c
b/net/netfilter/xt_state.c
index d9010b1..df37b91 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
 -50,22
+50,18  static int check(const char *tablename,
 		 void *matchinfo,
 		 unsigned int hook_mask)
 {
-#if defined(CONFIG_NF_CONNTRACK) ||
defined(CONFIG_NF_CONNTRACK_MODULE)
 	if (nf_ct_l3proto_try_module_get(match->family) < 0)
{
-		printk(KERN_WARNING "can't load nf_conntrack support
for "
+		printk(KERN_WARNING "can't load conntrack support
for "
 				    "proto=%dn", match->family);
 		return 0;
 	}
-#endif
 	return 1;
 }
 
 static void
 destroy(const struct xt_match *match, void *matchinfo)
 {
-#if defined(CONFIG_NF_CONNTRACK) ||
defined(CONFIG_NF_CONNTRACK_MODULE)
 	nf_ct_l3proto_module_put(match->family);
-#endif
 }
 
 static struct xt_match xt_state_match[] = {
 -91,7
+87,6  static struct xt_match xt_state_match[] 
 
 static int __init xt_state_init(void)
 {
-	need_conntrack();
 	return xt_register_matches(xt_state_match,
ARRAY_SIZE(xt_state_match));
 }
 

x_tables: add missing try to load conntrack from match/targets
user name
2006-12-12 08:06:24
[NETFILTER]: x_tables: add missing try to load conntrack
from match/targets

CLUSTERIP, CONNMARK, CONNSECMARK, and connbytes need
ip_conntrack or
layer 3 protocol module of nf_conntrack.

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakaitoshiba.co.jp>
Signed-off-by: Patrick McHardy <kabertrash.net>

---
commit c5cea7a103d6bc40bd6c84805ee38b0262632a4d
tree 6efd0e5354ce15b6c912eea12f95760523f0cd46
parent 806a57fff01366038e04747ea75adf2c7c5db09f
author Yasuyuki Kozakai <yasuyuki.kozakaitoshiba.co.jp> Tue, 12 Dec 2006 08:50:46 +0100
committer Patrick McHardy <kabertrash.net> Tue, 12 Dec
2006 08:50:46 +0100

 net/ipv4/netfilter/ipt_CLUSTERIP.c |    8 ++++++++
 net/netfilter/xt_CONNMARK.c        |   14 +++++++++++++-
 net/netfilter/xt_CONNSECMARK.c     |   14 +++++++++++++-
 net/netfilter/xt_connbytes.c       |   14 ++++++++++++++
 4 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c
b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index fef56ae..b1c1116 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
 -447,6
+447,12  checkentry(const char *tablename,
 		cipinfo->config = config;
 	}
 
+	if (nf_ct_l3proto_try_module_get(target->family) <
0) {
+		printk(KERN_WARNING "can't load conntrack support
for "
+				    "proto=%dn", target->family);
+		return 0;
+	}
+
 	return 1;
 }
 
 -460,6
+466,8  static void destroy(const struct xt_targ
 	clusterip_config_entry_put(cipinfo->config);
 
 	clusterip_config_put(cipinfo->config);
+
+	nf_ct_l3proto_module_put(target->family);
 }
 
 static struct ipt_target clusterip_tgt = {
diff --git a/net/netfilter/xt_CONNMARK.c
b/net/netfilter/xt_CONNMARK.c
index b554823..0534bfa 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
 -96,6
+96,11  checkentry(const char *tablename,
 {
 	struct xt_connmark_target_info *matchinfo = targinfo;
 
+	if (nf_ct_l3proto_try_module_get(target->family) <
0) {
+		printk(KERN_WARNING "can't load conntrack support
for "
+				    "proto=%dn", target->family);
+		return 0;
+	}
 	if (matchinfo->mode == XT_CONNMARK_RESTORE) {
 		if (strcmp(tablename, "mangle") != 0) {
 			printk(KERN_WARNING "CONNMARK: restore can only be
"
 -111,6
+116,12  checkentry(const char *tablename,
 	return 1;
 }
 
+static void
+destroy(const struct xt_target *target, void *targinfo)
+{
+	nf_ct_l3proto_module_put(target->family);
+}
+
 #ifdef CONFIG_COMPAT
 struct compat_xt_connmark_target_info {
 	compat_ulong_t	mark, mask;
 -147,6
+158,7  static struct xt_target xt_connmark_targ
 		.name		= "CONNMARK",
 		.family		= AF_INET,
 		.checkentry	= checkentry,
+		.destroy	= destroy,
 		.target		= target,
 		.targetsize	= sizeof(struct xt_connmark_target_info),
 #ifdef CONFIG_COMPAT
 -160,6
+172,7  #endif
 		.name		= "CONNMARK",
 		.family		= AF_INET6,
 		.checkentry	= checkentry,
+		.destroy	= destroy,
 		.target		= target,
 		.targetsize	= sizeof(struct xt_connmark_target_info),
 		.me		= THIS_MODULE
 -168,7
+181,6  #endif
 
 static int __init xt_connmark_init(void)
 {
-	need_conntrack();
 	return xt_register_targets(xt_connmark_target,
 				   ARRAY_SIZE(xt_connmark_target));
 }
diff --git a/net/netfilter/xt_CONNSECMARK.c
b/net/netfilter/xt_CONNSECMARK.c
index 4673862..a3fe3c3 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
 -93,6
+93,11  static int checkentry(const char *tablen
 {
 	struct xt_connsecmark_target_info *info = targinfo;
 
+	if (nf_ct_l3proto_try_module_get(target->family) <
0) {
+		printk(KERN_WARNING "can't load conntrack support
for "
+				    "proto=%dn", target->family);
+		return 0;
+	}
 	switch (info->mode) {
 	case CONNSECMARK_SAVE:
 	case CONNSECMARK_RESTORE:
 -106,11
+111,18  static int checkentry(const char *tablen
 	return 1;
 }
 
+static void
+destroy(const struct xt_target *target, void *targinfo)
+{
+	nf_ct_l3proto_module_put(target->family);
+}
+
 static struct xt_target xt_connsecmark_target[] = {
 	{
 		.name		= "CONNSECMARK",
 		.family		= AF_INET,
 		.checkentry	= checkentry,
+		.destroy	= destroy,
 		.target		= target,
 		.targetsize	= sizeof(struct xt_connsecmark_target_info),
 		.table		= "mangle",
 -120,6
+132,7  static struct xt_target xt_connsecmark_t
 		.name		= "CONNSECMARK",
 		.family		= AF_INET6,
 		.checkentry	= checkentry,
+		.destroy	= destroy,
 		.target		= target,
 		.targetsize	= sizeof(struct xt_connsecmark_target_info),
 		.table		= "mangle",
 -129,7
+142,6  static struct xt_target xt_connsecmark_t
 
 static int __init xt_connsecmark_init(void)
 {
-	need_conntrack();
 	return xt_register_targets(xt_connsecmark_target,
 				   ARRAY_SIZE(xt_connsecmark_target));
 }
diff --git a/net/netfilter/xt_connbytes.c
b/net/netfilter/xt_connbytes.c
index dcc497e..d93cb09 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
 -139,15
+139,28  static int check(const char *tablename,
 	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
 		return 0;
 
+	if (nf_ct_l3proto_try_module_get(match->family) < 0)
{
+		printk(KERN_WARNING "can't load conntrack support
for "
+				    "proto=%dn", match->family);
+		return 0;
+	}
+
 	return 1;
 }
 
+static void
+destroy(const struct xt_match *match, void *matchinfo)
+{
+	nf_ct_l3proto_module_put(match->family);
+}
+
 static struct xt_match xt_connbytes_match[] = {
 	{
 		.name		= "connbytes",
 		.family		= AF_INET,
 		.checkentry	= check,
 		.match		= match,
+		.destroy	= destroy,
 		.matchsize	= sizeof(struct xt_connbytes_info),
 		.me		= THIS_MODULE
 	},
 -156,6
+169,7  static struct xt_match xt_connbytes_matc
 		.family		= AF_INET6,
 		.checkentry	= check,
 		.match		= match,
+		.destroy	= destroy,
 		.matchsize	= sizeof(struct xt_connbytes_info),
 		.me		= THIS_MODULE
 	},

ip_tables: ipt and ipt_compat checks unification
user name
2006-12-12 08:06:25
[NETFILTER]: ip_tables: ipt and ipt_compat checks
unification

Matches and targets verification is duplicated in normal and
compat processing
ways. This patch refactors code in order to remove this.

Signed-off-by: Dmitry Mishin <dimopenvz.org>
Signed-off-by: Patrick McHardy <kabertrash.net>

---
commit b364d80996eb9ebd18b443dac82cb6c47b72f381
tree 0b1401ba60b9e71a34812664de56c61425db5589
parent c5cea7a103d6bc40bd6c84805ee38b0262632a4d
author Dmitry Mishin <dimopenvz.org> Tue, 12 Dec
2006 08:50:48 +0100
committer Patrick McHardy <kabertrash.net> Tue, 12 Dec
2006 08:50:48 +0100

 net/ipv4/netfilter/ip_tables.c |  176
++++++++++++++++++----------------------
 1 files changed, 79 insertions(+), 97 deletions(-)

diff --git a/net/ipv4/netfilter/ip_tables.c
b/net/ipv4/netfilter/ip_tables.c
index 0ff2956..83ebbeb 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
 -484,7
+484,47  cleanup_match(struct ipt_entry_match *m,
 }
 
 static inline int
-check_match(struct ipt_entry_match *m,
+check_entry(struct ipt_entry *e, const char *name)
+{
+	struct ipt_entry_target *t;
+
+	if (!ip_checkentry(&e->ip)) {
+		duprintf("ip_tables: ip check failed %p %s.n",
e, name);
+		return -EINVAL;
+	}
+
+	if (e->target_offset + sizeof(struct ipt_entry_target)
> e->next_offset)
+		return -EINVAL;
+
+	t = ipt_get_target(e);
+	if (e->target_offset + t->u.target_size >
e->next_offset)
+		return -EINVAL;
+
+	return 0;
+}
+
+static inline int check_match(struct ipt_entry_match *m,
const char *name,
+				const struct ipt_ip *ip, unsigned int hookmask)
+{
+	struct ipt_match *match;
+	int ret;
+
+	match = m->u.kernel.match;
+	ret = xt_check_match(match, AF_INET, m->u.match_size -
sizeof(*m),
+			     name, hookmask, ip->proto,
+			     ip->invflags & IPT_INV_PROTO);
+	if (!ret && m->u.kernel.match->checkentry
+	    && !m->u.kernel.match->checkentry(name,
ip, match, m->data,
+					      hookmask)) {
+		duprintf("ip_tables: check failed for `%s'.n",
+			 m->u.kernel.match->name);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static inline int
+find_check_match(struct ipt_entry_match *m,
 	    const char *name,
 	    const struct ipt_ip *ip,
 	    unsigned int hookmask,
 -497,26
+537,15  check_match(struct ipt_entry_match *m,
 						   m->u.user.revision),
 					"ipt_%s", m->u.user.name);
 	if (IS_ERR(match) || !match) {
-		duprintf("check_match: `%s' not foundn",
m->u.user.name);
+		duprintf("find_check_match: `%s' not foundn",
m->u.user.name);
 		return match ? PTR_ERR(match) : -ENOENT;
 	}
 	m->u.kernel.match = match;
 
-	ret = xt_check_match(match, AF_INET, m->u.match_size -
sizeof(*m),
-			     name, hookmask, ip->proto,
-			     ip->invflags & IPT_INV_PROTO);
+	ret = check_match(m, name, ip, hookmask);
 	if (ret)
 		goto err;
 
-	if (m->u.kernel.match->checkentry
-	    && !m->u.kernel.match->checkentry(name,
ip, match, m->data,
-					      hookmask)) {
-		duprintf("ip_tables: check failed for `%s'.n",
-			 m->u.kernel.match->name);
-		ret = -EINVAL;
-		goto err;
-	}
-
 	(*i)++;
 	return 0;
 err:
 -524,10
+553,29  err:
 	return ret;
 }
 
-static struct ipt_target ipt_standard_target;
+static inline int check_target(struct ipt_entry *e, const
char *name)
+{
+ 	struct ipt_entry_target *t;
+ 	struct ipt_target *target;
+ 	int ret;
+
+	t = ipt_get_target(e);
+	target = t->u.kernel.target;
+	ret = xt_check_target(target, AF_INET, t->u.target_size
- sizeof(*t),
+			      name, e->comefrom, e->ip.proto,
+			      e->ip.invflags & IPT_INV_PROTO);
+	if (!ret && t->u.kernel.target->checkentry
+		   && !t->u.kernel.target->checkentry(name,
e, target,
+						      t->data, e->comefrom)) {
+		duprintf("ip_tables: check failed for `%s'.n",
+			 t->u.kernel.target->name);
+		ret = -EINVAL;
+	}
+	return ret;
+}
 
 static inline int
-check_entry(struct ipt_entry *e, const char *name, unsigned
int size,
+find_check_entry(struct ipt_entry *e, const char *name,
unsigned int size,
 	    unsigned int *i)
 {
 	struct ipt_entry_target *t;
 -535,49
+583,32  check_entry(struct ipt_entry *e, const c
 	int ret;
 	unsigned int j;
 
-	if (!ip_checkentry(&e->ip)) {
-		duprintf("ip_tables: ip check failed %p %s.n",
e, name);
-		return -EINVAL;
-	}
-
-	if (e->target_offset + sizeof(struct ipt_entry_target)
> e->next_offset)
-		return -EINVAL;
+	ret = check_entry(e, name);
+	if (ret)
+		return ret;
 
 	j = 0;
-	ret = IPT_MATCH_ITERATE(e, check_match, name,
&e->ip, e->comefrom, &j);
+	ret = IPT_MATCH_ITERATE(e, find_check_match, name,
&e->ip,
+							e->comefrom, &j);
 	if (ret != 0)
 		goto cleanup_matches;
 
 	t = ipt_get_target(e);
-	ret = -EINVAL;
-	if (e->target_offset + t->u.target_size >
e->next_offset)
-			goto cleanup_matches;
 	target = try_then_request_module(xt_find_target(AF_INET,
 						     t->u.user.name,
 						     t->u.user.revision),
 					 "ipt_%s", t->u.user.name);
 	if (IS_ERR(target) || !target) {
-		duprintf("check_entry: `%s' not foundn",
t->u.user.name);
+		duprintf("find_check_entry: `%s' not foundn",
t->u.user.name);
 		ret = target ? PTR_ERR(target) : -ENOENT;
 		goto cleanup_matches;
 	}
 	t->u.kernel.target = target;
 
-	ret = xt_check_target(target, AF_INET, t->u.target_size
- sizeof(*t),
-			      name, e->comefrom, e->ip.proto,
-			      e->ip.invflags & IPT_INV_PROTO);
+	ret = check_target(e, name);
 	if (ret)
 		goto err;
 
-	if (t->u.kernel.target->checkentry
-		   && !t->u.kernel.target->checkentry(name,
e, target, t->data,
-						      e->comefrom)) {
-		duprintf("ip_tables: check failed for `%s'.n",
-			 t->u.kernel.target->name);
-		ret = -EINVAL;
-		goto err;
-	}
-
 	(*i)++;
 	return 0;
  err:
 -712,7
+743,7  translate_table(const char *name,
 	/* Finally, each sanity check must pass */
 	i = 0;
 	ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
-				check_entry, name, size, &i);
+				find_check_entry, name, size, &i);
 
 	if (ret != 0) {
 		IPT_ENTRY_ITERATE(entry0, newinfo->size,
 -1452,14
+1483,9  check_compat_entry_size_and_hooks(struct
 		return -EINVAL;
 	}
 
-	if (!ip_checkentry(&e->ip)) {
-		duprintf("ip_tables: ip check failed %p %s.n",
e, name);
-		return -EINVAL;
-	}
-
-	if (e->target_offset + sizeof(struct
compat_xt_entry_target) >
-								e->next_offset)
-		return -EINVAL;
+	ret = check_entry(e, name);
+	if (ret)
+		return ret;
 
 	off = 0;
 	entry_offset = (void *)e - (void *)base;
 -1470,15
+1496,13  check_compat_entry_size_and_hooks(struct
 		goto cleanup_matches;
 
 	t = ipt_get_target(e);
-	ret = -EINVAL;
-	if (e->target_offset + t->u.target_size >
e->next_offset)
-			goto cleanup_matches;
 	target = try_then_request_module(xt_find_target(AF_INET,
 						     t->u.user.name,
 						     t->u.user.revision),
 					 "ipt_%s", t->u.user.name);
 	if (IS_ERR(target) || !target) {
-		duprintf("check_entry: `%s' not foundn",
t->u.user.name);
+		duprintf("check_compat_entry_size_and_hooks: `%s'
not foundn",
+							t->u.user.name);
 		ret = target ? PTR_ERR(target) : -ENOENT;
 		goto cleanup_matches;
 	}
 -1555,57
+1579,15  static int compat_copy_entry_from_user(s
 	return ret;
 }
 
-static inline int compat_check_match(struct ipt_entry_match
*m, const char *name,
-				const struct ipt_ip *ip, unsigned int hookmask)
-{
-	struct ipt_match *match;
-	int ret;
-
-	match = m->u.kernel.match;
-	ret = xt_check_match(match, AF_INET, m->u.match_size -
sizeof(*m),
-			     name, hookmask, ip->proto,
-			     ip->invflags & IPT_INV_PROTO);
-	if (!ret && m->u.kernel.match->checkentry
-	    && !m->u.kernel.match->checkentry(name,
ip, match, m->data,
-					      hookmask)) {
-		duprintf("ip_tables: compat: check failed for
`%s'.n",
-			 m->u.kernel.match->name);
-		ret = -EINVAL;
-	}
-	return ret;
-}
-
-static inline int compat_check_target(struct ipt_entry *e,
const char *name)
-{
- 	struct ipt_entry_target *t;
- 	struct ipt_target *target;
- 	int ret;
-
-	t = ipt_get_target(e);
-	target = t->u.kernel.target;
-	ret = xt_check_target(target, AF_INET, t->u.target_size
- sizeof(*t),
-			      name, e->comefrom, e->ip.proto,
-			      e->ip.invflags & IPT_INV_PROTO);
-	if (!ret && t->u.kernel.target->checkentry
-		   && !t->u.kernel.target->checkentry(name,
e, target,
-						      t->data, e->comefrom)) {
-		duprintf("ip_tables: compat: check failed for
`%s'.n",
-			 t->u.kernel.target->name);
-		ret = -EINVAL;
-	}
-	return ret;
-}
-
 static inline int compat_check_entry(struct ipt_entry *e,
const char *name)
 {
 	int ret;
 
-	ret = IPT_MATCH_ITERATE(e, compat_check_match, name,
&e->ip,
-								e->comefrom);
+	ret = IPT_MATCH_ITERATE(e, check_match, name,
&e->ip, e->comefrom);
 	if (ret)
 		return ret;
 
-	return compat_check_target(e, name);
+	return check_target(e, name);
 }
 
 static int

{ip, ip6, arp}_tables: fix exponential worst-case search for loops
user name
2006-12-12 08:06:26
[NETFILTER]: {ip,ip6,arp}_tables: fix exponential worst-case
search for loops

If we come to node we'd already marked as seen and it's not
a part of path
(i.e. we don't have a loop right there), we already know
that it isn't a
part of any loop, so we don't need to revisit it.

That speeds the things up if some chain is refered to from
several places
and kills O(exp(table size)) worst-case behaviour (without
sleeping,
at that, so if you manage to self-LART that way, you are SOL
for a long
time)...

Signed-off-by: Al Viro <virozeniv.linux.org.uk>
Signed-off-by: Patrick McHardy <kabertrash.net>

---
commit 1ed7c34fb5da5919a9b0fcae5299b8297ccae21d
tree 645eafd9a55aba9b094826489e0a44482ab9a62d
parent b364d80996eb9ebd18b443dac82cb6c47b72f381
author Al Viro <virozeniv.linux.org.uk> Tue, 12 Dec 2006
08:50:50 +0100
committer Patrick McHardy <kabertrash.net> Tue, 12 Dec
2006 08:50:50 +0100

 net/ipv4/netfilter/arp_tables.c |    5 +++--
 net/ipv4/netfilter/ip_tables.c  |    5 +++--
 net/ipv6/netfilter/ip6_tables.c |    5 +++--
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/ipv4/netfilter/arp_tables.c
b/net/ipv4/netfilter/arp_tables.c
index 71b76ad..9aa2239 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
 -358,6
+358,7  static int mark_source_chains(struct xt_
 		for (;;) {
 			struct arpt_standard_target *t
 				= (void *)arpt_get_target(e);
+			int visited = e->comefrom & (1 << hook);
 
 			if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) {
 				printk("arptables: loop hook %u pos %u
%08X.n",
 -368,11
+369,11  static int mark_source_chains(struct xt_
 				|= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));
 
 			/* Unconditional return/END. */
-			if (e->target_offset == sizeof(struct arpt_entry)
+			if ((e->target_offset == sizeof(struct arpt_entry)
 			    && (strcmp(t->target.u.user.name,
 				       ARPT_STANDARD_TARGET) == 0)
 			    && t->verdict < 0
-			    && unconditional(&e->arp)) {
+			    && unconditional(&e->arp)) ||
visited) {
 				unsigned int oldpos, size;
 
 				if (t->verdict < -NF_MAX_VERDICT - 1) {
diff --git a/net/ipv4/netfilter/ip_tables.c
b/net/ipv4/netfilter/ip_tables.c
index 83ebbeb..09696f1 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
 -384,6
+384,7  mark_source_chains(struct xt_table_info 
 		for (;;) {
 			struct ipt_standard_target *t
 				= (void *)ipt_get_target(e);
+			int visited = e->comefrom & (1 << hook);
 
 			if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
 				printk("iptables: loop hook %u pos %u
%08X.n",
 -394,11
+395,11  mark_source_chains(struct xt_table_info 
 				|= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
 
 			/* Unconditional return/END. */
-			if (e->target_offset == sizeof(struct ipt_entry)
+			if ((e->target_offset == sizeof(struct ipt_entry)
 			    && (strcmp(t->target.u.user.name,
 				       IPT_STANDARD_TARGET) == 0)
 			    && t->verdict < 0
-			    && unconditional(&e->ip)) {
+			    && unconditional(&e->ip)) || visited)
{
 				unsigned int oldpos, size;
 
 				if (t->verdict < -NF_MAX_VERDICT - 1) {
diff --git a/net/ipv6/netfilter/ip6_tables.c
b/net/ipv6/netfilter/ip6_tables.c
index 4eec4b3..99502c5 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
 -413,6
+413,7  mark_source_chains(struct xt_table_info 
 		unsigned int pos = newinfo->hook_entry[hook];
 		struct ip6t_entry *e
 			= (struct ip6t_entry *)(entry0 + pos);
+		int visited = e->comefrom & (1 << hook);
 
 		if (!(valid_hooks & (1 << hook)))
 			continue;
 -433,11
+434,11  mark_source_chains(struct xt_table_info 
 				|= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
 
 			/* Unconditional return/END. */
-			if (e->target_offset == sizeof(struct ip6t_entry)
+			if ((e->target_offset == sizeof(struct ip6t_entry)
 			    && (strcmp(t->target.u.user.name,
 				       IP6T_STANDARD_TARGET) == 0)
 			    && t->verdict < 0
-			    && unconditional(&e->ipv6)) {
+			    && unconditional(&e->ipv6)) ||
visited) {
 				unsigned int oldpos, size;
 
 				if (t->verdict < -NF_MAX_VERDICT - 1) {

Netfilter fixes
user name
2006-12-12 08:30:57
From: Patrick McHardy <kabertrash.net>
Date: Tue, 12 Dec 2006 09:06:18 +0100 (MET)

> following are a few netfilter fixes (mostly conntrack
related), a
> patch to unify the iptables compat and non-compat
verification code
> and Al Viro's iptables loop check optimization with
similar changes
> to ip6_tables and arp_tables.

All patches applied and pushed out to my net-2.6 tree.

Thanks a lot.

[1-8]

about | contact  Other archives ( Real Estate discussion Medical topics )