Blame SOURCES/0023-fix-direct-rule-order-with-multiple-address-with-s-d.patch

63f414
From 44dff592c200f81d74b64ba1c729ec8ec3b8612e Mon Sep 17 00:00:00 2001
63f414
From: Eric Garver <eric@garver.life>
63f414
Date: Tue, 13 Apr 2021 14:35:31 -0400
63f414
Subject: [PATCH 23/30] fix(direct): rule order with multiple address with
63f414
 -s/-d
63f414
63f414
Fixes: rhbz 1940928
63f414
Fixes: rhbz 1949552
63f414
(cherry picked from commit 2be50d366b9ba073e5f86edcd0b412ff48c3fed1)
63f414
(cherry picked from commit a545183d6916169cd16648707b9f876ea0833955)
63f414
---
63f414
 src/firewall/core/fw_direct.py | 53 +++++++++++++++++++++++++++++-----
63f414
 src/firewall/core/ipXtables.py | 32 --------------------
63f414
 2 files changed, 46 insertions(+), 39 deletions(-)
63f414
63f414
diff --git a/src/firewall/core/fw_direct.py b/src/firewall/core/fw_direct.py
63f414
index e53a72e3326a..76aeda9f19cb 100644
63f414
--- a/src/firewall/core/fw_direct.py
63f414
+++ b/src/firewall/core/fw_direct.py
63f414
@@ -298,7 +298,7 @@ class FirewallDirect(object):
63f414
                 r.append((ipv, table, chain, priority, list(args)))
63f414
         return r
63f414
 
63f414
-    def _register_rule(self, rule_id, chain_id, priority, enable):
63f414
+    def _register_rule(self, rule_id, chain_id, priority, enable, count):
63f414
         if enable:
63f414
             if chain_id not in self._rules:
63f414
                 self._rules[chain_id] = LastUpdatedOrderedDict()
63f414
@@ -307,14 +307,14 @@ class FirewallDirect(object):
63f414
                 self._rule_priority_positions[chain_id] = { }
63f414
 
63f414
             if priority in self._rule_priority_positions[chain_id]:
63f414
-                self._rule_priority_positions[chain_id][priority] += 1
63f414
+                self._rule_priority_positions[chain_id][priority] += count
63f414
             else:
63f414
-                self._rule_priority_positions[chain_id][priority] = 1
63f414
+                self._rule_priority_positions[chain_id][priority] = count
63f414
         else:
63f414
             del self._rules[chain_id][rule_id]
63f414
             if len(self._rules[chain_id]) == 0:
63f414
                 del self._rules[chain_id]
63f414
-            self._rule_priority_positions[chain_id][priority] -= 1
63f414
+            self._rule_priority_positions[chain_id][priority] -= count
63f414
 
63f414
     # DIRECT PASSTHROUGH (untracked)
63f414
 
63f414
@@ -376,6 +376,34 @@ class FirewallDirect(object):
63f414
                 r.append(list(args))
63f414
         return r
63f414
 
63f414
+    def split_value(self, rules, opts):
63f414
+        """Split values combined with commas for options in opts"""
63f414
+
63f414
+        out_rules = [ ]
63f414
+        for rule in rules:
63f414
+            processed = False
63f414
+            for opt in opts:
63f414
+                try:
63f414
+                    i = rule.index(opt)
63f414
+                except ValueError:
63f414
+                    pass
63f414
+                else:
63f414
+                    if len(rule) > i and "," in rule[i+1]:
63f414
+                        # For all items in the comma separated list in index
63f414
+                        # i of the rule, a new rule is created with a single
63f414
+                        # item from this list
63f414
+                        processed = True
63f414
+                        items = rule[i+1].split(",")
63f414
+                        for item in items:
63f414
+                            _rule = rule[:]
63f414
+                            _rule[i+1] = item
63f414
+                            out_rules.append(_rule)
63f414
+            if not processed:
63f414
+                out_rules.append(rule)
63f414
+
63f414
+        return out_rules
63f414
+
63f414
+
63f414
     def _rule(self, enable, ipv, table, chain, priority, args, transaction):
63f414
         self._check_ipv_table(ipv, table)
63f414
         # Do not create zone chains if we're using nftables. Only allow direct
63f414
@@ -458,6 +486,7 @@ class FirewallDirect(object):
63f414
         # has index 1.
63f414
 
63f414
         index = 1
63f414
+        count = 0
63f414
         if chain_id in self._rule_priority_positions:
63f414
             positions = sorted(self._rule_priority_positions[chain_id].keys())
63f414
             j = 0
63f414
@@ -465,11 +494,21 @@ class FirewallDirect(object):
63f414
                 index += self._rule_priority_positions[chain_id][positions[j]]
63f414
                 j += 1
63f414
 
63f414
-        transaction.add_rule(backend, backend.build_rule(enable, table, _chain, index, args))
63f414
+        # split the direct rule in some cases as iptables-restore can't handle
63f414
+        # compound args.
63f414
+        #
63f414
+        args_list = [list(args)]
63f414
+        args_list = self.split_value(args_list, [ "-s", "--source" ])
63f414
+        args_list = self.split_value(args_list, [ "-d", "--destination" ])
63f414
+
63f414
+        for _args in args_list:
63f414
+            transaction.add_rule(backend, backend.build_rule(enable, table, _chain, index, tuple(_args)))
63f414
+            index += 1
63f414
+            count += 1
63f414
 
63f414
-        self._register_rule(rule_id, chain_id, priority, enable)
63f414
+        self._register_rule(rule_id, chain_id, priority, enable, count)
63f414
         transaction.add_fail(self._register_rule,
63f414
-                             rule_id, chain_id, priority, not enable)
63f414
+                             rule_id, chain_id, priority, not enable, count)
63f414
 
63f414
     def _chain(self, add, ipv, table, chain, transaction):
63f414
         self._check_ipv_table(ipv, table)
63f414
diff --git a/src/firewall/core/ipXtables.py b/src/firewall/core/ipXtables.py
63f414
index 968b75867849..818ce3f153d0 100644
63f414
--- a/src/firewall/core/ipXtables.py
63f414
+++ b/src/firewall/core/ipXtables.py
63f414
@@ -200,36 +200,6 @@ class ip4tables(object):
63f414
                                                      " ".join(_args), ret))
63f414
         return ret
63f414
 
63f414
-    def split_value(self, rules, opts=None):
63f414
-        """Split values combined with commas for options in opts"""
63f414
-
63f414
-        if opts is None:
63f414
-            return rules
63f414
-
63f414
-        out_rules = [ ]
63f414
-        for rule in rules:
63f414
-            processed = False
63f414
-            for opt in opts:
63f414
-                try:
63f414
-                    i = rule.index(opt)
63f414
-                except ValueError:
63f414
-                    pass
63f414
-                else:
63f414
-                    if len(rule) > i and "," in rule[i+1]:
63f414
-                        # For all items in the comma separated list in index
63f414
-                        # i of the rule, a new rule is created with a single
63f414
-                        # item from this list
63f414
-                        processed = True
63f414
-                        items = rule[i+1].split(",")
63f414
-                        for item in items:
63f414
-                            _rule = rule[:]
63f414
-                            _rule[i+1] = item
63f414
-                            out_rules.append(_rule)
63f414
-            if not processed:
63f414
-                out_rules.append(rule)
63f414
-
63f414
-        return out_rules
63f414
-
63f414
     def _rule_replace(self, rule, pattern, replacement):
63f414
         try:
63f414
             i = rule.index(pattern)
63f414
@@ -472,8 +442,6 @@ class ip4tables(object):
63f414
 
63f414
         for table in table_rules:
63f414
             rules = table_rules[table]
63f414
-            rules = self.split_value(rules, [ "-s", "--source" ])
63f414
-            rules = self.split_value(rules, [ "-d", "--destination" ])
63f414
 
63f414
             temp_file.write("*%s\n" % table)
63f414
             for rule in rules:
63f414
-- 
63f414
2.27.0
63f414