]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
netfilter: {ip,ip6,arp}_tables: fix incorrect loop detection
authorPatrick McHardy <kaber@trash.net>
Wed, 25 Mar 2009 18:26:35 +0000 (19:26 +0100)
committerPatrick McHardy <kaber@trash.net>
Wed, 25 Mar 2009 18:26:35 +0000 (19:26 +0100)
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>
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv6/netfilter/ip6_tables.c

index 4b35dba7cf7d937c898affad1fefb6bbe8a84461..4f454ce9a602da8a6a6492cf5e4c0753ec3166fa 100644 (file)
@@ -388,7 +388,9 @@ static int mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->arp)) || visited) {
                                unsigned int oldpos, size;
 
-                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                               if ((strcmp(t->target.u.user.name,
+                                           ARPT_STANDARD_TARGET) == 0) &&
+                                   t->verdict < -NF_MAX_VERDICT - 1) {
                                        duprintf("mark_source_chains: bad "
                                                "negative verdict (%i)\n",
                                                                t->verdict);
index 41c59e391a6a91e55a4a9fdca2b10d4961d4eb84..82ee7c9049ff032d0f652bc114b0b237e6d374d1 100644 (file)
@@ -488,7 +488,9 @@ mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->ip)) || visited) {
                                unsigned int oldpos, size;
 
-                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                               if ((strcmp(t->target.u.user.name,
+                                           IPT_STANDARD_TARGET) == 0) &&
+                                   t->verdict < -NF_MAX_VERDICT - 1) {
                                        duprintf("mark_source_chains: bad "
                                                "negative verdict (%i)\n",
                                                                t->verdict);
index e59662b3b5b9de4477a0c4364b6dd4e55ab2e615..e89cfa3a8f254650948f60ada09982b9862c745d 100644 (file)
@@ -517,7 +517,9 @@ mark_source_chains(struct xt_table_info *newinfo,
                            && unconditional(&e->ipv6)) || visited) {
                                unsigned int oldpos, size;
 
-                               if (t->verdict < -NF_MAX_VERDICT - 1) {
+                               if ((strcmp(t->target.u.user.name,
+                                           IP6T_STANDARD_TARGET) == 0) &&
+                                   t->verdict < -NF_MAX_VERDICT - 1) {
                                        duprintf("mark_source_chains: bad "
                                                "negative verdict (%i)\n",
                                                                t->verdict);