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

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