aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2009-03-25 14:26:35 -0400
committerPatrick McHardy <kaber@trash.net>2009-03-25 14:26:35 -0400
commit1f9352ae2253a97b07b34dcf16ffa3b4ca12c558 (patch)
treee6d487c5d0dd82da34b53cc64bfd7c2d5e9f98f1 /net
parentaf9d32ad6718b9a80fa89f557cc1fbb63a93ec15 (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.c4
-rw-r--r--net/ipv4/netfilter/ip_tables.c4
-rw-r--r--net/ipv6/netfilter/ip6_tables.c4
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);