diff options
author | Patrick McHardy <kaber@trash.net> | 2009-03-25 14:26:35 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-03-25 14:26:35 -0400 |
commit | 1f9352ae2253a97b07b34dcf16ffa3b4ca12c558 (patch) | |
tree | e6d487c5d0dd82da34b53cc64bfd7c2d5e9f98f1 /net | |
parent | af9d32ad6718b9a80fa89f557cc1fbb63a93ec15 (diff) |
netfilter: {ip,ip6,arp}_tables: fix incorrect loop detection
Commit e1b4b9f ([NETFILTER]: {ip,ip6,arp}_tables: fix exponential worst-case
search for loops) introduced a regression in the loop detection algorithm,
causing sporadic incorrectly detected loops.
When a chain has already been visited during the check, it is treated as
having a standard target containing a RETURN verdict directly at the
beginning in order to not check it again. The real target of the first
rule is then incorrectly treated as STANDARD target and checked not to
contain invalid verdicts.
Fix by making sure the rule does actually contain a standard target.
Based on patch by Francis Dupont <Francis_Dupont@isc.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 4 |
3 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 4b35dba7cf7d..4f454ce9a602 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -388,7 +388,9 @@ static int mark_source_chains(struct xt_table_info *newinfo, | |||
388 | && unconditional(&e->arp)) || visited) { | 388 | && unconditional(&e->arp)) || visited) { |
389 | unsigned int oldpos, size; | 389 | unsigned int oldpos, size; |
390 | 390 | ||
391 | if (t->verdict < -NF_MAX_VERDICT - 1) { | 391 | if ((strcmp(t->target.u.user.name, |
392 | ARPT_STANDARD_TARGET) == 0) && | ||
393 | t->verdict < -NF_MAX_VERDICT - 1) { | ||
392 | duprintf("mark_source_chains: bad " | 394 | duprintf("mark_source_chains: bad " |
393 | "negative verdict (%i)\n", | 395 | "negative verdict (%i)\n", |
394 | t->verdict); | 396 | t->verdict); |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 41c59e391a6a..82ee7c9049ff 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -488,7 +488,9 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
488 | && unconditional(&e->ip)) || visited) { | 488 | && unconditional(&e->ip)) || visited) { |
489 | unsigned int oldpos, size; | 489 | unsigned int oldpos, size; |
490 | 490 | ||
491 | if (t->verdict < -NF_MAX_VERDICT - 1) { | 491 | if ((strcmp(t->target.u.user.name, |
492 | IPT_STANDARD_TARGET) == 0) && | ||
493 | t->verdict < -NF_MAX_VERDICT - 1) { | ||
492 | duprintf("mark_source_chains: bad " | 494 | duprintf("mark_source_chains: bad " |
493 | "negative verdict (%i)\n", | 495 | "negative verdict (%i)\n", |
494 | t->verdict); | 496 | t->verdict); |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index e59662b3b5b9..e89cfa3a8f25 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -517,7 +517,9 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
517 | && unconditional(&e->ipv6)) || visited) { | 517 | && unconditional(&e->ipv6)) || visited) { |
518 | unsigned int oldpos, size; | 518 | unsigned int oldpos, size; |
519 | 519 | ||
520 | if (t->verdict < -NF_MAX_VERDICT - 1) { | 520 | if ((strcmp(t->target.u.user.name, |
521 | IP6T_STANDARD_TARGET) == 0) && | ||
522 | t->verdict < -NF_MAX_VERDICT - 1) { | ||
521 | duprintf("mark_source_chains: bad " | 523 | duprintf("mark_source_chains: bad " |
522 | "negative verdict (%i)\n", | 524 | "negative verdict (%i)\n", |
523 | t->verdict); | 525 | t->verdict); |