|
List Info
Thread: Netfilter fixes
|
|
| Netfilter fixes |

|
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 |

|
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.foerster gmx.de>.
Signed-off-by: Patrick McHardy <kaber trash.net>
---
commit 61ca98ed893d16bccb077bb88496d1e24b8604b2
tree 3adad9d96f832d98af105010eb3aaed0c9a83338
parent e63abb7bc148c5410f48496f8c339956947a1afb
author Patrick McHardy <kaber trash.net> Tue, 12 Dec
2006 08:50:36 +0100
committer Patrick McHardy <kaber trash.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 |

|
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.kozakai toshiba.co.jp>
Signed-off-by: Patrick McHardy <kaber trash.net>
---
commit bc5ca5410c8fa8930ea4cf55ae034e163cb02b76
tree d7ab6180d2a687ff2edd5478d9bc1f276262321f
parent 61ca98ed893d16bccb077bb88496d1e24b8604b2
author Yasuyuki Kozakai <yasuyuki.kozakai toshiba.co.jp> Tue, 12 Dec 2006 08:50:38 +0100
committer Patrick McHardy <kaber trash.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 |

|
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.kozakai toshiba.co.jp>
Signed-off-by: Patrick McHardy <kaber trash.net>
---
commit 806a57fff01366038e04747ea75adf2c7c5db09f
tree 70890f4a68f8422b0daaf7e20b5ba23e3afdf1e7
parent bc5ca5410c8fa8930ea4cf55ae034e163cb02b76
author Yasuyuki Kozakai <yasuyuki.kozakai toshiba.co.jp> Tue, 12 Dec 2006 08:50:42 +0100
committer Patrick McHardy <kaber trash.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 <marc mbsi.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 <gandalf netfilter.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 |

|
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.kozakai toshiba.co.jp>
Signed-off-by: Patrick McHardy <kaber trash.net>
---
commit c5cea7a103d6bc40bd6c84805ee38b0262632a4d
tree 6efd0e5354ce15b6c912eea12f95760523f0cd46
parent 806a57fff01366038e04747ea75adf2c7c5db09f
author Yasuyuki Kozakai <yasuyuki.kozakai toshiba.co.jp> Tue, 12 Dec 2006 08:50:46 +0100
committer Patrick McHardy <kaber trash.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 |

|
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 <dim openvz.org>
Signed-off-by: Patrick McHardy <kaber trash.net>
---
commit b364d80996eb9ebd18b443dac82cb6c47b72f381
tree 0b1401ba60b9e71a34812664de56c61425db5589
parent c5cea7a103d6bc40bd6c84805ee38b0262632a4d
author Dmitry Mishin <dim openvz.org> Tue, 12 Dec
2006 08:50:48 +0100
committer Patrick McHardy <kaber trash.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 |

|
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 <viro zeniv.linux.org.uk>
Signed-off-by: Patrick McHardy <kaber trash.net>
---
commit 1ed7c34fb5da5919a9b0fcae5299b8297ccae21d
tree 645eafd9a55aba9b094826489e0a44482ab9a62d
parent b364d80996eb9ebd18b443dac82cb6c47b72f381
author Al Viro <viro zeniv.linux.org.uk> Tue, 12 Dec 2006
08:50:50 +0100
committer Patrick McHardy <kaber trash.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 |

|
2006-12-12 08:30:57 |
From: Patrick McHardy <kaber trash.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]
|
|