Blame SOURCES/0001-fw-if-startup-fails-on-reload-reapply-non-perm-confi.patch

4d71d0
From 17470fa9deac4aa15ecf75b9c811c093bc44c019 Mon Sep 17 00:00:00 2001
4d71d0
From: Eric Garver <e@erig.me>
4d71d0
Date: Fri, 17 Aug 2018 12:26:53 -0400
4d71d0
Subject: [PATCH 1/2] fw: if startup fails on reload, reapply non-perm config
4d71d0
 that survives reload
4d71d0
4d71d0
Even if startup fails we should still re-assign the non-permanent
4d71d0
interfaces to zones and non-permanent direct rules.
4d71d0
4d71d0
Fixes: rhbz 1498923
4d71d0
(cherry picked from commit 2796edc1691f52c3655991c0be814a617cb26910)
4d71d0
---
4d71d0
 src/firewall/core/fw.py             | 121 +++++++++++++++-------------
4d71d0
 src/tests/regression/rhbz1498923.at |  17 ++++
4d71d0
 2 files changed, 80 insertions(+), 58 deletions(-)
4d71d0
4d71d0
diff --git a/src/firewall/core/fw.py b/src/firewall/core/fw.py
4d71d0
index 5b706d6d3e80..9079f1bbc6a4 100644
4d71d0
--- a/src/firewall/core/fw.py
4d71d0
+++ b/src/firewall/core/fw.py
4d71d0
@@ -910,70 +910,75 @@ class Firewall(object):
4d71d0
     def reload(self, stop=False):
4d71d0
         _panic = self._panic
4d71d0
 
4d71d0
-        try:
4d71d0
-            # save zone interfaces
4d71d0
-            _zone_interfaces = { }
4d71d0
-            for zone in self.zone.get_zones():
4d71d0
-                _zone_interfaces[zone] = self.zone.get_settings(zone)["interfaces"]
4d71d0
-            # save direct config
4d71d0
-            _direct_config = self.direct.get_runtime_config()
4d71d0
-            _old_dz = self.get_default_zone()
4d71d0
-
4d71d0
-            # stop
4d71d0
-            self.cleanup()
4d71d0
+        # save zone interfaces
4d71d0
+        _zone_interfaces = { }
4d71d0
+        for zone in self.zone.get_zones():
4d71d0
+            _zone_interfaces[zone] = self.zone.get_settings(zone)["interfaces"]
4d71d0
+        # save direct config
4d71d0
+        _direct_config = self.direct.get_runtime_config()
4d71d0
+        _old_dz = self.get_default_zone()
4d71d0
+
4d71d0
+        # stop
4d71d0
+        self.cleanup()
4d71d0
 
4d71d0
-            self.set_policy("DROP")
4d71d0
+        self.set_policy("DROP")
4d71d0
 
4d71d0
+        start_exception = None
4d71d0
+        try:
4d71d0
             self._start(reload=True, complete_reload=stop)
4d71d0
-
4d71d0
-            # handle interfaces in the default zone and move them to the new
4d71d0
-            # default zone if it changed
4d71d0
-            _new_dz = self.get_default_zone()
4d71d0
-            if _new_dz != _old_dz:
4d71d0
-                # if_new_dz has been introduced with the reload, we need to add it
4d71d0
-                # https://github.com/firewalld/firewalld/issues/53
4d71d0
-                if _new_dz not in _zone_interfaces:
4d71d0
-                    _zone_interfaces[_new_dz] = { }
4d71d0
-                # default zone changed. Move interfaces from old default zone to
4d71d0
-                # the new one.
4d71d0
-                for iface, settings in list(_zone_interfaces[_old_dz].items()):
4d71d0
-                    if settings["__default__"]:
4d71d0
-                        # move only those that were added to default zone
4d71d0
-                        # (not those that were added to specific zone same as
4d71d0
-                        # default)
4d71d0
-                        _zone_interfaces[_new_dz][iface] = \
4d71d0
-                            _zone_interfaces[_old_dz][iface]
4d71d0
-                        del _zone_interfaces[_old_dz][iface]
4d71d0
-
4d71d0
-            # add interfaces to zones again
4d71d0
-            for zone in self.zone.get_zones():
4d71d0
-                if zone in _zone_interfaces:
4d71d0
-                    self.zone.set_settings(zone, { "interfaces":
4d71d0
-                                                   _zone_interfaces[zone] })
4d71d0
-                    del _zone_interfaces[zone]
4d71d0
-                else:
4d71d0
-                    log.info1("New zone '%s'.", zone)
4d71d0
-            if len(_zone_interfaces) > 0:
4d71d0
-                for zone in list(_zone_interfaces.keys()):
4d71d0
-                    log.info1("Lost zone '%s', zone interfaces dropped.", zone)
4d71d0
-                    del _zone_interfaces[zone]
4d71d0
-            del _zone_interfaces
4d71d0
-
4d71d0
-            # restore direct config
4d71d0
-            self.direct.set_config(_direct_config)
4d71d0
-
4d71d0
-            # enable panic mode again if it has been enabled before or set policy
4d71d0
-            # to ACCEPT
4d71d0
-            if _panic:
4d71d0
-                self.enable_panic_mode()
4d71d0
+        except Exception as e:
4d71d0
+            # save the exception for later, but continue restoring interfaces,
4d71d0
+            # etc. We'll re-raise it at the end.
4d71d0
+            start_exception = e
4d71d0
+
4d71d0
+        # handle interfaces in the default zone and move them to the new
4d71d0
+        # default zone if it changed
4d71d0
+        _new_dz = self.get_default_zone()
4d71d0
+        if _new_dz != _old_dz:
4d71d0
+            # if_new_dz has been introduced with the reload, we need to add it
4d71d0
+            # https://github.com/firewalld/firewalld/issues/53
4d71d0
+            if _new_dz not in _zone_interfaces:
4d71d0
+                _zone_interfaces[_new_dz] = { }
4d71d0
+            # default zone changed. Move interfaces from old default zone to
4d71d0
+            # the new one.
4d71d0
+            for iface, settings in list(_zone_interfaces[_old_dz].items()):
4d71d0
+                if settings["__default__"]:
4d71d0
+                    # move only those that were added to default zone
4d71d0
+                    # (not those that were added to specific zone same as
4d71d0
+                    # default)
4d71d0
+                    _zone_interfaces[_new_dz][iface] = \
4d71d0
+                        _zone_interfaces[_old_dz][iface]
4d71d0
+                    del _zone_interfaces[_old_dz][iface]
4d71d0
+
4d71d0
+        # add interfaces to zones again
4d71d0
+        for zone in self.zone.get_zones():
4d71d0
+            if zone in _zone_interfaces:
4d71d0
+                self.zone.set_settings(zone, { "interfaces":
4d71d0
+                                               _zone_interfaces[zone] })
4d71d0
+                del _zone_interfaces[zone]
4d71d0
             else:
4d71d0
-                self.set_policy("ACCEPT")
4d71d0
+                log.info1("New zone '%s'.", zone)
4d71d0
+        if len(_zone_interfaces) > 0:
4d71d0
+            for zone in list(_zone_interfaces.keys()):
4d71d0
+                log.info1("Lost zone '%s', zone interfaces dropped.", zone)
4d71d0
+                del _zone_interfaces[zone]
4d71d0
+        del _zone_interfaces
4d71d0
+
4d71d0
+        # restore direct config
4d71d0
+        self.direct.set_config(_direct_config)
4d71d0
+
4d71d0
+        # enable panic mode again if it has been enabled before or set policy
4d71d0
+        # to ACCEPT
4d71d0
+        if _panic:
4d71d0
+            self.enable_panic_mode()
4d71d0
+        else:
4d71d0
+            self.set_policy("ACCEPT")
4d71d0
 
4d71d0
-            self._state = "RUNNING"
4d71d0
-        except Exception:
4d71d0
+        if start_exception:
4d71d0
             self._state = "FAILED"
4d71d0
-            self.set_policy("ACCEPT")
4d71d0
-            raise
4d71d0
+            raise start_exception
4d71d0
+        else:
4d71d0
+            self._state = "RUNNING"
4d71d0
 
4d71d0
     # STATE
4d71d0
 
4d71d0
diff --git a/src/tests/regression/rhbz1498923.at b/src/tests/regression/rhbz1498923.at
4d71d0
index bb0d841db2a7..9b68678180ef 100644
4d71d0
--- a/src/tests/regression/rhbz1498923.at
4d71d0
+++ b/src/tests/regression/rhbz1498923.at
4d71d0
@@ -1,11 +1,28 @@
4d71d0
 FWD_START_TEST([invalid direct rule causes reload error])
4d71d0
 FWD_CHECK([-q --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 8080 -j ACCEPT])
4d71d0
 FWD_CHECK([-q --permanent --direct --add-rule ipv4 filter INPUT 1 --a-bogus-flag])
4d71d0
+
4d71d0
+dnl add some non-permanent things that should persist a reload
4d71d0
+FWD_CHECK([-q --zone=public --add-interface=foobar0])
4d71d0
+FWD_CHECK([-q --direct --direct --add-rule ipv4 filter FORWARD 0 -p tcp -j ACCEPT])
4d71d0
+
4d71d0
 FWD_RELOAD(13, [ignore], [ignore], 251)
4d71d0
 FWD_CHECK([--state], 251, [ignore], [failed
4d71d0
 ])
4d71d0
 
4d71d0
+dnl verify the non-permanent stuff we set above remained
4d71d0
+FWD_CHECK([--get-zone-of-interface=foobar0], 0, [dnl
4d71d0
+public
4d71d0
+])
4d71d0
+FWD_CHECK([-q --direct --direct --query-rule ipv4 filter FORWARD 0 -p tcp -j ACCEPT])
4d71d0
+
4d71d0
 dnl now remove the bad rule and reload successfully
4d71d0
 FWD_CHECK([-q --permanent --direct --remove-rule ipv4 filter INPUT 1 --a-bogus-flag])
4d71d0
 FWD_RELOAD
4d71d0
+
4d71d0
+dnl verify the non-permanent stuff we set above remained
4d71d0
+FWD_CHECK([--get-zone-of-interface=foobar0], 0, [dnl
4d71d0
+public
4d71d0
+])
4d71d0
+FWD_CHECK([-q --direct --direct --query-rule ipv4 filter FORWARD 0 -p tcp -j ACCEPT])
4d71d0
 FWD_END_TEST([-e '/.*a-bogus-flag.*/d'])
4d71d0
-- 
4d71d0
2.18.0
4d71d0