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