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

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