|
|
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 |
|