Blame SOURCES/v1.0.0-0036-fix-ipset-disallow-overlapping-entries.patch

63f414
From 3d7ec2dabb164cbc2dce5aa8aa37ae156ebad275 Mon Sep 17 00:00:00 2001
63f414
From: Eric Garver <eric@garver.life>
63f414
Date: Tue, 23 Feb 2021 09:18:33 -0500
63f414
Subject: [PATCH 36/36] fix(ipset): disallow overlapping entries
63f414
63f414
These are already being blocked by the ipset backend, but we should
63f414
catch them higher up to avoid differences in the backends.
63f414
63f414
(cherry picked from commit 5b4e8918715a1d2e4abf77ed4eb3252486a19109)
63f414
---
63f414
 src/firewall/client.py                        |  4 +++-
63f414
 src/firewall/core/fw_ipset.py                 |  4 +++-
63f414
 src/firewall/core/ipset.py                    | 13 +++++++++++++
63f414
 src/firewall/server/config_ipset.py           |  5 ++++-
63f414
 src/tests/regression/ipset_netmask_allowed.at | 14 ++++++++------
63f414
 5 files changed, 31 insertions(+), 9 deletions(-)
63f414
63f414
diff --git a/src/firewall/client.py b/src/firewall/client.py
63f414
index aa6bd7cd282b..3715ffd29316 100644
63f414
--- a/src/firewall/client.py
63f414
+++ b/src/firewall/client.py
63f414
@@ -34,7 +34,7 @@ from firewall.core.base import DEFAULT_ZONE_TARGET, DEFAULT_POLICY_TARGET, DEFAU
63f414
 from firewall.dbus_utils import dbus_to_python
63f414
 from firewall.functions import b2u
63f414
 from firewall.core.rich import Rich_Rule
63f414
-from firewall.core.ipset import normalize_ipset_entry
63f414
+from firewall.core.ipset import normalize_ipset_entry, check_entry_overlaps_existing
63f414
 from firewall import errors
63f414
 from firewall.errors import FirewallError
63f414
 
63f414
@@ -1619,6 +1619,7 @@ class FirewallClientIPSetSettings(object):
63f414
             raise FirewallError(errors.IPSET_WITH_TIMEOUT)
63f414
         _entries = set()
63f414
         for _entry in dbus_to_python(entries, list):
63f414
+            check_entry_overlaps_existing(_entry, _entries)
63f414
             _entries.add(normalize_ipset_entry(_entry))
63f414
         self.settings[5] = list(_entries)
63f414
     @handle_exceptions
63f414
@@ -1628,6 +1629,7 @@ class FirewallClientIPSetSettings(object):
63f414
             raise FirewallError(errors.IPSET_WITH_TIMEOUT)
63f414
         entry = normalize_ipset_entry(entry)
63f414
         if entry not in self.settings[5]:
63f414
+            check_entry_overlaps_existing(entry, self.settings[5])
63f414
             self.settings[5].append(entry)
63f414
         else:
63f414
             raise FirewallError(errors.ALREADY_ENABLED, entry)
63f414
diff --git a/src/firewall/core/fw_ipset.py b/src/firewall/core/fw_ipset.py
63f414
index e5348949413c..a285fd4a4aab 100644
63f414
--- a/src/firewall/core/fw_ipset.py
63f414
+++ b/src/firewall/core/fw_ipset.py
63f414
@@ -25,7 +25,7 @@ __all__ = [ "FirewallIPSet" ]
63f414
 
63f414
 from firewall.core.logger import log
63f414
 from firewall.core.ipset import remove_default_create_options as rm_def_cr_opts, \
63f414
-                                normalize_ipset_entry
63f414
+                                normalize_ipset_entry, check_entry_overlaps_existing
63f414
 from firewall.core.io.ipset import IPSet
63f414
 from firewall import errors
63f414
 from firewall.errors import FirewallError
63f414
@@ -196,6 +196,7 @@ class FirewallIPSet(object):
63f414
         if entry in obj.entries:
63f414
             raise FirewallError(errors.ALREADY_ENABLED,
63f414
                                 "'%s' already is in '%s'" % (entry, name))
63f414
+        check_entry_overlaps_existing(entry, obj.entries)
63f414
 
63f414
         try:
63f414
             for backend in self.backends():
63f414
@@ -245,6 +246,7 @@ class FirewallIPSet(object):
63f414
 
63f414
         _entries = set()
63f414
         for _entry in entries:
63f414
+            check_entry_overlaps_existing(_entry, _entries)
63f414
             _entries.add(normalize_ipset_entry(_entry))
63f414
         entries = list(_entries)
63f414
 
63f414
diff --git a/src/firewall/core/ipset.py b/src/firewall/core/ipset.py
63f414
index 5bb21856f648..d6defa395241 100644
63f414
--- a/src/firewall/core/ipset.py
63f414
+++ b/src/firewall/core/ipset.py
63f414
@@ -302,3 +302,16 @@ def normalize_ipset_entry(entry):
63f414
             _entry.append(_part)
63f414
 
63f414
     return ",".join(_entry)
63f414
+
63f414
+def check_entry_overlaps_existing(entry, entries):
63f414
+    """ Check if entry overlaps any entry in the list of entries """
63f414
+    # Only check simple types
63f414
+    if len(entry.split(",")) > 1:
63f414
+        return
63f414
+
63f414
+    for itr in entries:
63f414
+        try:
63f414
+            if ipaddress.ip_network(itr, strict=False).overlaps(ipaddress.ip_network(entry, strict=False)):
63f414
+                raise FirewallError(errors.INVALID_ENTRY, "Entry '{}' overlaps with existing entry '{}'".format(itr, entry))
63f414
+        except ValueError:
63f414
+            pass
63f414
diff --git a/src/firewall/server/config_ipset.py b/src/firewall/server/config_ipset.py
63f414
index 18ef5783de62..f33c2a02926f 100644
63f414
--- a/src/firewall/server/config_ipset.py
63f414
+++ b/src/firewall/server/config_ipset.py
63f414
@@ -33,7 +33,8 @@ from firewall.dbus_utils import dbus_to_python, \
63f414
     dbus_introspection_prepare_properties, \
63f414
     dbus_introspection_add_properties
63f414
 from firewall.core.io.ipset import IPSet
63f414
-from firewall.core.ipset import IPSET_TYPES, normalize_ipset_entry
63f414
+from firewall.core.ipset import IPSET_TYPES, normalize_ipset_entry, \
63f414
+                                check_entry_overlaps_existing
63f414
 from firewall.core.logger import log
63f414
 from firewall.server.decorators import handle_exceptions, \
63f414
     dbus_handle_exceptions, dbus_service_method
63f414
@@ -408,6 +409,7 @@ class FirewallDConfigIPSet(slip.dbus.service.Object):
63f414
     def setEntries(self, entries, sender=None):
63f414
         _entries = set()
63f414
         for _entry in dbus_to_python(entries, list):
63f414
+            check_entry_overlaps_existing(_entry, _entries)
63f414
             _entries.add(normalize_ipset_entry(_entry))
63f414
         entries = list(_entries)
63f414
         log.debug1("%s.setEntries('[%s]')", self._log_prefix,
63f414
@@ -432,6 +434,7 @@ class FirewallDConfigIPSet(slip.dbus.service.Object):
63f414
             raise FirewallError(errors.IPSET_WITH_TIMEOUT)
63f414
         if entry in settings[5]:
63f414
             raise FirewallError(errors.ALREADY_ENABLED, entry)
63f414
+        check_entry_overlaps_existing(entry, settings[5])
63f414
         settings[5].append(entry)
63f414
         self.update(settings)
63f414
 
63f414
diff --git a/src/tests/regression/ipset_netmask_allowed.at b/src/tests/regression/ipset_netmask_allowed.at
63f414
index b5165d94b220..fd08afd3b57c 100644
63f414
--- a/src/tests/regression/ipset_netmask_allowed.at
63f414
+++ b/src/tests/regression/ipset_netmask_allowed.at
63f414
@@ -9,15 +9,17 @@ dnl an add for the whole range. i.e. 1.2.3.4/24  --> 1.2.3.[0.255] (256
63f414
 dnl entries).
63f414
 dnl
63f414
 dnl In nftables, we allow this by using actual intervals.
63f414
-FWD_CHECK([--permanent --ipset foobar --add-entry 1.2.3.0/24], 0, [ignore])
63f414
-FWD_CHECK([            --ipset foobar --add-entry 1.2.3.0/24], 0, [ignore])
63f414
+FWD_CHECK([--permanent --ipset foobar --add-entry 1.2.3.4/24], 0, [ignore])
63f414
+FWD_CHECK([            --ipset foobar --add-entry 1.2.3.4/24], 0, [ignore])
63f414
 
63f414
 dnl check the edge case
63f414
 FWD_CHECK([--permanent --ipset foobar --add-entry 4.3.2.1/32], 0, [ignore])
63f414
 FWD_CHECK([            --ipset foobar --add-entry 4.3.2.1/32], 0, [ignore])
63f414
 
63f414
-dnl overlaps should be denied by ipset
63f414
-FWD_CHECK([            --ipset foobar --add-entry 1.2.3.0/22], 13, [ignore], [ignore])
63f414
-FWD_CHECK([            --ipset foobar --add-entry 1.2.3.0/30], 13, [ignore], [ignore])
63f414
+dnl overlaps should be denied
63f414
+FWD_CHECK([--permanent --ipset foobar --add-entry 1.2.3.0/22], 136, [ignore], [ignore])
63f414
+FWD_CHECK([            --ipset foobar --add-entry 1.2.3.0/22], 136, [ignore], [ignore])
63f414
+FWD_CHECK([--permanent --ipset foobar --add-entry 1.2.3.4/30], 136, [ignore], [ignore])
63f414
+FWD_CHECK([            --ipset foobar --add-entry 1.2.3.4/30], 136, [ignore], [ignore])
63f414
 
63f414
-FWD_END_TEST([-e '/ERROR: COMMAND_FAILED:/d'])
63f414
+FWD_END_TEST([-e '/ERROR: INVALID_ENTRY:/d'])
63f414
-- 
63f414
2.27.0
63f414