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.
191 lines
7.6 KiB
191 lines
7.6 KiB
6 years ago
|
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
|
||
|
|