Blame SOURCES/firewalld-0.7-0002-ipXtables-Avoid-inserting-rules-with-index.patch

21c891
From e7a361474d58b66fcd1c135cf465f0308cf3f8cb Mon Sep 17 00:00:00 2001
21c891
From: Eric Garver <eric@garver.life>
21c891
Date: Thu, 10 Jan 2019 13:02:34 -0500
21c891
Subject: [PATCH 2/3] ipXtables: Avoid inserting rules with index
21c891
21c891
iptables-restore (nftables) has a bug in which inserting by index
21c891
doesn't always work as expected. Rules may be inserted at the wrong
21c891
index. We can mostly avoid this by appending rules. This actually
21c891
simplifies things because we don't have to count indexes. Ref rhbz
21c891
1647925.
21c891
21c891
(cherry picked from commit 9f0eb929c240211d3da978732a9f6930da71486c)
21c891
---
21c891
 src/firewall/core/fw_direct.py |   5 +-
21c891
 src/firewall/core/ipXtables.py | 260 ++++++++++++++++-----------------
21c891
 2 files changed, 134 insertions(+), 131 deletions(-)
21c891
21c891
diff --git a/src/firewall/core/fw_direct.py b/src/firewall/core/fw_direct.py
21c891
index 94196e8a41fa..e53a72e3326a 100644
21c891
--- a/src/firewall/core/fw_direct.py
21c891
+++ b/src/firewall/core/fw_direct.py
21c891
@@ -181,7 +181,10 @@ class FirewallDirect(object):
21c891
     def _check_builtin_chain(self, ipv, table, chain):
21c891
         if ipv in ['ipv4', 'ipv6']:
21c891
             built_in_chains = ipXtables.BUILT_IN_CHAINS[table]
21c891
-            our_chains = ipXtables.OUR_CHAINS[table]
21c891
+            if self._fw.nftables_enabled:
21c891
+                our_chains = {}
21c891
+            else:
21c891
+                our_chains = self._fw.get_direct_backend_by_ipv(ipv).our_chains[table]
21c891
         else:
21c891
             built_in_chains = ebtables.BUILT_IN_CHAINS[table]
21c891
             our_chains = ebtables.OUR_CHAINS[table]
21c891
diff --git a/src/firewall/core/ipXtables.py b/src/firewall/core/ipXtables.py
21c891
index 2d2d9f76d5c9..c5b17aa3a846 100644
21c891
--- a/src/firewall/core/ipXtables.py
21c891
+++ b/src/firewall/core/ipXtables.py
21c891
@@ -51,106 +51,6 @@ ICMP = {
21c891
     "ipv6": "ipv6-icmp",
21c891
 }
21c891
 
21c891
-DEFAULT_RULES = { }
21c891
-LOG_RULES = { }
21c891
-OUR_CHAINS = {} # chains created by firewalld
21c891
-
21c891
-DEFAULT_RULES["security"] = [ ]
21c891
-OUR_CHAINS["security"] = set()
21c891
-for chain in BUILT_IN_CHAINS["security"]:
21c891
-    DEFAULT_RULES["security"].append("-N %s_direct" % chain)
21c891
-    DEFAULT_RULES["security"].append("-I %s 1 -j %s_direct" % (chain, chain))
21c891
-    OUR_CHAINS["security"].add("%s_direct" % chain)
21c891
-
21c891
-DEFAULT_RULES["raw"] = [ ]
21c891
-OUR_CHAINS["raw"] = set()
21c891
-for chain in BUILT_IN_CHAINS["raw"]:
21c891
-    DEFAULT_RULES["raw"].append("-N %s_direct" % chain)
21c891
-    DEFAULT_RULES["raw"].append("-I %s 1 -j %s_direct" % (chain, chain))
21c891
-    OUR_CHAINS["raw"].add("%s_direct" % chain)
21c891
-
21c891
-    if chain == "PREROUTING":
21c891
-        DEFAULT_RULES["raw"].append("-N %s_ZONES_SOURCE" % chain)
21c891
-        DEFAULT_RULES["raw"].append("-N %s_ZONES" % chain)
21c891
-        DEFAULT_RULES["raw"].append("-I %s 2 -j %s_ZONES_SOURCE" % (chain, chain))
21c891
-        DEFAULT_RULES["raw"].append("-I %s 3 -j %s_ZONES" % (chain, chain))
21c891
-        OUR_CHAINS["raw"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
21c891
-
21c891
-DEFAULT_RULES["mangle"] = [ ]
21c891
-OUR_CHAINS["mangle"] = set()
21c891
-for chain in BUILT_IN_CHAINS["mangle"]:
21c891
-    DEFAULT_RULES["mangle"].append("-N %s_direct" % chain)
21c891
-    DEFAULT_RULES["mangle"].append("-I %s 1 -j %s_direct" % (chain, chain))
21c891
-    OUR_CHAINS["mangle"].add("%s_direct" % chain)
21c891
-
21c891
-    if chain == "PREROUTING":
21c891
-        DEFAULT_RULES["mangle"].append("-N %s_ZONES_SOURCE" % chain)
21c891
-        DEFAULT_RULES["mangle"].append("-N %s_ZONES" % chain)
21c891
-        DEFAULT_RULES["mangle"].append("-I %s 2 -j %s_ZONES_SOURCE" % (chain, chain))
21c891
-        DEFAULT_RULES["mangle"].append("-I %s 3 -j %s_ZONES" % (chain, chain))
21c891
-        OUR_CHAINS["mangle"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
21c891
-
21c891
-DEFAULT_RULES["nat"] = [ ]
21c891
-OUR_CHAINS["nat"] = set()
21c891
-for chain in BUILT_IN_CHAINS["nat"]:
21c891
-    DEFAULT_RULES["nat"].append("-N %s_direct" % chain)
21c891
-    DEFAULT_RULES["nat"].append("-I %s 1 -j %s_direct" % (chain, chain))
21c891
-    OUR_CHAINS["nat"].add("%s_direct" % chain)
21c891
-
21c891
-    if chain in [ "PREROUTING", "POSTROUTING" ]:
21c891
-        DEFAULT_RULES["nat"].append("-N %s_ZONES_SOURCE" % chain)
21c891
-        DEFAULT_RULES["nat"].append("-N %s_ZONES" % chain)
21c891
-        DEFAULT_RULES["nat"].append("-I %s 2 -j %s_ZONES_SOURCE" % (chain, chain))
21c891
-        DEFAULT_RULES["nat"].append("-I %s 3 -j %s_ZONES" % (chain, chain))
21c891
-        OUR_CHAINS["nat"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
21c891
-
21c891
-DEFAULT_RULES["filter"] = [
21c891
-    "-N INPUT_direct",
21c891
-    "-N INPUT_ZONES_SOURCE",
21c891
-    "-N INPUT_ZONES",
21c891
-
21c891
-    "-I INPUT 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",
21c891
-    "-I INPUT 2 -i lo -j ACCEPT",
21c891
-    "-I INPUT 3 -j INPUT_direct",
21c891
-    "-I INPUT 4 -j INPUT_ZONES_SOURCE",
21c891
-    "-I INPUT 5 -j INPUT_ZONES",
21c891
-    "-I INPUT 6 -m conntrack --ctstate INVALID -j DROP",
21c891
-    "-I INPUT 7 -j %%REJECT%%",
21c891
-
21c891
-    "-N FORWARD_direct",
21c891
-    "-N FORWARD_IN_ZONES_SOURCE",
21c891
-    "-N FORWARD_IN_ZONES",
21c891
-    "-N FORWARD_OUT_ZONES_SOURCE",
21c891
-    "-N FORWARD_OUT_ZONES",
21c891
-
21c891
-    "-I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",
21c891
-    "-I FORWARD 2 -i lo -j ACCEPT",
21c891
-    "-I FORWARD 3 -j FORWARD_direct",
21c891
-    "-I FORWARD 4 -j FORWARD_IN_ZONES_SOURCE",
21c891
-    "-I FORWARD 5 -j FORWARD_IN_ZONES",
21c891
-    "-I FORWARD 6 -j FORWARD_OUT_ZONES_SOURCE",
21c891
-    "-I FORWARD 7 -j FORWARD_OUT_ZONES",
21c891
-    "-I FORWARD 8 -m conntrack --ctstate INVALID -j DROP",
21c891
-    "-I FORWARD 9 -j %%REJECT%%",
21c891
-
21c891
-    "-N OUTPUT_direct",
21c891
-
21c891
-    "-I OUTPUT 1 -j OUTPUT_direct",
21c891
-]
21c891
-
21c891
-LOG_RULES["filter"] = [
21c891
-    "-I INPUT 6 -m conntrack --ctstate INVALID %%LOGTYPE%% -j LOG --log-prefix 'STATE_INVALID_DROP: '",
21c891
-    "-I INPUT 8 %%LOGTYPE%% -j LOG --log-prefix 'FINAL_REJECT: '",
21c891
-
21c891
-    "-I FORWARD 8 -m conntrack --ctstate INVALID %%LOGTYPE%% -j LOG --log-prefix 'STATE_INVALID_DROP: '",
21c891
-    "-I FORWARD 10 %%LOGTYPE%% -j LOG --log-prefix 'FINAL_REJECT: '",
21c891
-]
21c891
-
21c891
-OUR_CHAINS["filter"] = set(["INPUT_direct", "INPUT_ZONES_SOURCE", "INPUT_ZONES",
21c891
-                            "FORWARD_direct", "FORWARD_IN_ZONES_SOURCE",
21c891
-                            "FORWARD_IN_ZONES", "FORWARD_OUT_ZONES_SOURCE",
21c891
-                            "FORWARD_OUT_ZONES", "OUTPUT_direct"])
21c891
-
21c891
 # ipv ebtables also uses this
21c891
 #
21c891
 def common_reverse_rule(args):
21c891
@@ -278,6 +178,7 @@ class ip4tables(object):
21c891
         self.fill_exists()
21c891
         self.available_tables = []
21c891
         self.rich_rule_priority_counts = {}
21c891
+        self.our_chains = {} # chains created by firewalld
21c891
 
21c891
     def fill_exists(self):
21c891
         self.command_exists = os.path.exists(self._command)
21c891
@@ -694,20 +595,117 @@ class ip4tables(object):
21c891
         return []
21c891
 
21c891
     def build_default_rules(self, log_denied="off"):
21c891
-        default_rules = []
21c891
-        for table in DEFAULT_RULES:
21c891
+        default_rules = {}
21c891
+
21c891
+        default_rules["security"] = [ ]
21c891
+        self.our_chains["security"] = set()
21c891
+        for chain in BUILT_IN_CHAINS["security"]:
21c891
+            default_rules["security"].append("-N %s_direct" % chain)
21c891
+            default_rules["security"].append("-A %s -j %s_direct" % (chain, chain))
21c891
+            self.our_chains["security"].add("%s_direct" % chain)
21c891
+
21c891
+        default_rules["raw"] = [ ]
21c891
+        self.our_chains["raw"] = set()
21c891
+        for chain in BUILT_IN_CHAINS["raw"]:
21c891
+            default_rules["raw"].append("-N %s_direct" % chain)
21c891
+            default_rules["raw"].append("-A %s -j %s_direct" % (chain, chain))
21c891
+            self.our_chains["raw"].add("%s_direct" % chain)
21c891
+
21c891
+            if chain == "PREROUTING":
21c891
+                default_rules["raw"].append("-N %s_ZONES_SOURCE" % chain)
21c891
+                default_rules["raw"].append("-N %s_ZONES" % chain)
21c891
+                default_rules["raw"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
21c891
+                default_rules["raw"].append("-A %s -j %s_ZONES" % (chain, chain))
21c891
+                self.our_chains["raw"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
21c891
+
21c891
+        default_rules["mangle"] = [ ]
21c891
+        self.our_chains["mangle"] = set()
21c891
+        for chain in BUILT_IN_CHAINS["mangle"]:
21c891
+            default_rules["mangle"].append("-N %s_direct" % chain)
21c891
+            default_rules["mangle"].append("-A %s -j %s_direct" % (chain, chain))
21c891
+            self.our_chains["mangle"].add("%s_direct" % chain)
21c891
+
21c891
+            if chain == "PREROUTING":
21c891
+                default_rules["mangle"].append("-N %s_ZONES_SOURCE" % chain)
21c891
+                default_rules["mangle"].append("-N %s_ZONES" % chain)
21c891
+                default_rules["mangle"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
21c891
+                default_rules["mangle"].append("-A %s -j %s_ZONES" % (chain, chain))
21c891
+                self.our_chains["mangle"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
21c891
+
21c891
+        default_rules["nat"] = [ ]
21c891
+        self.our_chains["nat"] = set()
21c891
+        for chain in BUILT_IN_CHAINS["nat"]:
21c891
+            default_rules["nat"].append("-N %s_direct" % chain)
21c891
+            default_rules["nat"].append("-A %s -j %s_direct" % (chain, chain))
21c891
+            self.our_chains["nat"].add("%s_direct" % chain)
21c891
+
21c891
+            if chain in [ "PREROUTING", "POSTROUTING" ]:
21c891
+                default_rules["nat"].append("-N %s_ZONES_SOURCE" % chain)
21c891
+                default_rules["nat"].append("-N %s_ZONES" % chain)
21c891
+                default_rules["nat"].append("-A %s -j %s_ZONES_SOURCE" % (chain, chain))
21c891
+                default_rules["nat"].append("-A %s -j %s_ZONES" % (chain, chain))
21c891
+                self.our_chains["nat"].update(set(["%s_ZONES_SOURCE" % chain, "%s_ZONES" % chain]))
21c891
+
21c891
+        default_rules["filter"] = [
21c891
+            "-N INPUT_direct",
21c891
+            "-N INPUT_ZONES_SOURCE",
21c891
+            "-N INPUT_ZONES",
21c891
+
21c891
+            "-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",
21c891
+            "-A INPUT -i lo -j ACCEPT",
21c891
+            "-A INPUT -j INPUT_direct",
21c891
+            "-A INPUT -j INPUT_ZONES_SOURCE",
21c891
+            "-A INPUT -j INPUT_ZONES",
21c891
+        ]
21c891
+        if log_denied != "off":
21c891
+            default_rules["filter"].append("-A INPUT -m conntrack --ctstate INVALID %%LOGTYPE%% -j LOG --log-prefix 'STATE_INVALID_DROP: '")
21c891
+        default_rules["filter"].append("-A INPUT -m conntrack --ctstate INVALID -j DROP")
21c891
+        if log_denied != "off":
21c891
+            default_rules["filter"].append("-A INPUT %%LOGTYPE%% -j LOG --log-prefix 'FINAL_REJECT: '")
21c891
+        default_rules["filter"].append("-A INPUT -j %%REJECT%%")
21c891
+
21c891
+        default_rules["filter"] += [
21c891
+            "-N FORWARD_direct",
21c891
+            "-N FORWARD_IN_ZONES_SOURCE",
21c891
+            "-N FORWARD_IN_ZONES",
21c891
+            "-N FORWARD_OUT_ZONES_SOURCE",
21c891
+            "-N FORWARD_OUT_ZONES",
21c891
+
21c891
+            "-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",
21c891
+            "-A FORWARD -i lo -j ACCEPT",
21c891
+            "-A FORWARD -j FORWARD_direct",
21c891
+            "-A FORWARD -j FORWARD_IN_ZONES_SOURCE",
21c891
+            "-A FORWARD -j FORWARD_IN_ZONES",
21c891
+            "-A FORWARD -j FORWARD_OUT_ZONES_SOURCE",
21c891
+            "-A FORWARD -j FORWARD_OUT_ZONES",
21c891
+        ]
21c891
+        if log_denied != "off":
21c891
+            default_rules["filter"].append("-A FORWARD -m conntrack --ctstate INVALID %%LOGTYPE%% -j LOG --log-prefix 'STATE_INVALID_DROP: '")
21c891
+        default_rules["filter"].append("-A FORWARD -m conntrack --ctstate INVALID -j DROP")
21c891
+        if log_denied != "off":
21c891
+            default_rules["filter"].append("-A FORWARD %%LOGTYPE%% -j LOG --log-prefix 'FINAL_REJECT: '")
21c891
+        default_rules["filter"].append("-A FORWARD -j %%REJECT%%")
21c891
+
21c891
+        default_rules["filter"] += [
21c891
+            "-N OUTPUT_direct",
21c891
+
21c891
+            "-A OUTPUT -o lo -j ACCEPT",
21c891
+            "-A OUTPUT -j OUTPUT_direct",
21c891
+        ]
21c891
+
21c891
+        self.our_chains["filter"] = set(["INPUT_direct", "INPUT_ZONES_SOURCE", "INPUT_ZONES",
21c891
+                                    "FORWARD_direct", "FORWARD_IN_ZONES_SOURCE",
21c891
+                                    "FORWARD_IN_ZONES", "FORWARD_OUT_ZONES_SOURCE",
21c891
+                                    "FORWARD_OUT_ZONES", "OUTPUT_direct"])
21c891
+
21c891
+        final_default_rules = []
21c891
+        for table in default_rules:
21c891
             if table not in self.get_available_tables():
21c891
                 continue
21c891
-            _default_rules = DEFAULT_RULES[table][:]
21c891
-            if log_denied != "off" and table in LOG_RULES:
21c891
-                _default_rules.extend(LOG_RULES[table])
21c891
-            prefix = [ "-t", table ]
21c891
-            for rule in _default_rules:
21c891
-                if type(rule) == list:
21c891
-                    default_rules.append(prefix + rule)
21c891
-                else:
21c891
-                    default_rules.append(prefix + splitArgs(rule))
21c891
-        return default_rules
21c891
+            for rule in default_rules[table]:
21c891
+                final_default_rules.append(["-t", table] + splitArgs(rule))
21c891
+
21c891
+        return final_default_rules
21c891
 
21c891
     def get_zone_table_chains(self, table):
21c891
         if table == "filter":
21c891
@@ -801,7 +799,7 @@ class ip4tables(object):
21c891
     def build_zone_chain_rules(self, zone, table, chain):
21c891
         _zone = DEFAULT_ZONE_TARGET.format(chain=SHORTCUTS[chain], zone=zone)
21c891
 
21c891
-        OUR_CHAINS[table].update(set([_zone,
21c891
+        self.our_chains[table].update(set([_zone,
21c891
                                       "%s_log" % _zone,
21c891
                                       "%s_deny" % _zone,
21c891
                                       "%s_pre" % _zone,
21c891
@@ -815,35 +813,37 @@ class ip4tables(object):
21c891
         rules.append([ "-N", "%s_deny" % _zone, "-t", table ])
21c891
         rules.append([ "-N", "%s_allow" % _zone, "-t", table ])
21c891
         rules.append([ "-N", "%s_post" % _zone, "-t", table ])
21c891
-        rules.append([ "-I", _zone, "1", "-t", table, "-j", "%s_pre" % _zone ])
21c891
-        rules.append([ "-I", _zone, "2", "-t", table, "-j", "%s_log" % _zone ])
21c891
-        rules.append([ "-I", _zone, "3", "-t", table, "-j", "%s_deny" % _zone ])
21c891
-        rules.append([ "-I", _zone, "4", "-t", table, "-j", "%s_allow" % _zone ])
21c891
-        rules.append([ "-I", _zone, "5", "-t", table, "-j", "%s_post" % _zone ])
21c891
+        rules.append([ "-A", _zone, "-t", table, "-j", "%s_pre" % _zone ])
21c891
+        rules.append([ "-A", _zone, "-t", table, "-j", "%s_log" % _zone ])
21c891
+        rules.append([ "-A", _zone, "-t", table, "-j", "%s_deny" % _zone ])
21c891
+        rules.append([ "-A", _zone, "-t", table, "-j", "%s_allow" % _zone ])
21c891
+        rules.append([ "-A", _zone, "-t", table, "-j", "%s_post" % _zone ])
21c891
 
21c891
-        # Handle trust, block and drop zones:
21c891
-        # Add an additional rule with the zone target (accept, reject
21c891
-        # or drop) to the base zone only in the filter table.
21c891
-        # Otherwise it is not be possible to have a zone with drop
21c891
-        # target, that is allowing traffic that is locally initiated
21c891
-        # or that adds additional rules. (RHBZ#1055190)
21c891
         target = self._fw.zone._zones[zone].target
21c891
-        if table == "filter" and \
21c891
-           target in [ "ACCEPT", "REJECT", "%%REJECT%%", "DROP" ] and \
21c891
-           chain in [ "INPUT", "FORWARD_IN", "FORWARD_OUT", "OUTPUT" ]:
21c891
-            rules.append([ "-I", _zone, "6", "-t", table, "-j", target ])
21c891
 
21c891
         if self._fw.get_log_denied() != "off":
21c891
             if table == "filter" and \
21c891
                chain in [ "INPUT", "FORWARD_IN", "FORWARD_OUT", "OUTPUT" ]:
21c891
                 if target in [ "REJECT", "%%REJECT%%" ]:
21c891
-                    rules.append([ "-I", _zone, "6", "-t", table, "%%LOGTYPE%%",
21c891
+                    rules.append([ "-A", _zone, "-t", table, "%%LOGTYPE%%",
21c891
                                    "-j", "LOG", "--log-prefix",
21c891
                                    "\"%s_REJECT: \"" % _zone ])
21c891
                 if target == "DROP":
21c891
-                    rules.append([ "-I", _zone, "6", "-t", table, "%%LOGTYPE%%",
21c891
+                    rules.append([ "-A", _zone, "-t", table, "%%LOGTYPE%%",
21c891
                                    "-j", "LOG", "--log-prefix",
21c891
                                    "\"%s_DROP: \"" % _zone ])
21c891
+
21c891
+        # Handle trust, block and drop zones:
21c891
+        # Add an additional rule with the zone target (accept, reject
21c891
+        # or drop) to the base zone only in the filter table.
21c891
+        # Otherwise it is not be possible to have a zone with drop
21c891
+        # target, that is allowing traffic that is locally initiated
21c891
+        # or that adds additional rules. (RHBZ#1055190)
21c891
+        if table == "filter" and \
21c891
+           target in [ "ACCEPT", "REJECT", "%%REJECT%%", "DROP" ] and \
21c891
+           chain in [ "INPUT", "FORWARD_IN", "FORWARD_OUT", "OUTPUT" ]:
21c891
+            rules.append([ "-A", _zone, "-t", table, "-j", target ])
21c891
+
21c891
         return rules
21c891
 
21c891
     def _rule_limit(self, limit):
21c891
-- 
21c891
2.18.0
21c891