netfilter: {ip, ip6, arp}_tables: fix incorrect loop detection
authorPatrick McHardy <kaber@trash.net>
Mon, 6 Apr 2009 15:31:29 +0000 (17:31 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sat, 2 May 2009 17:56:47 +0000 (10:56 -0700)
upstream commit: 1f9352ae2253a97b07b34dcf16ffa3b4ca12c558

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>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv6/netfilter/ip6_tables.c

index 8d70d29f1ccf8b7664829f3c83a1e5cd4c579062..b1bd141e70c7dcf4aeb71bda380226c90253ff47 100644 (file)
@@ -374,7 +374,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 213fb27debc1e583adb548b4628ad0ac782d3492..3d471f8e26b9303c4e8b3ce17cfb278c243d2a0f 100644 (file)
@@ -500,7 +500,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 a33485dc81cb107e1cc343a764126325c9db2c05..def375b7fad588790214510f1142c64d6fd94ed4 100644 (file)
@@ -525,7 +525,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);