Blame SOURCES/0047-feat-config-add-CleanupModulesOnExit-configuration-o.patch

87a48e
From fb11903b8efd287f72e634fb8a4b4ff2034151fe Mon Sep 17 00:00:00 2001
87a48e
From: Paul Laufer <50234787+refual@users.noreply.github.com>
87a48e
Date: Fri, 27 Nov 2020 12:23:11 +0100
87a48e
Subject: [PATCH 47/48] feat(config): add CleanupModulesOnExit configuration
87a48e
 option
87a48e
87a48e
Fixes: rhbz 1520532
87a48e
Fixes: #533
87a48e
Closes: #721
87a48e
(cherry picked from commit 152a51537a7840afd0879ab4b60178bef4ec16a2)
87a48e
---
87a48e
 config/firewalld.conf                  |  9 +++++++-
87a48e
 doc/xml/firewalld.conf.xml             | 11 ++++++++++
87a48e
 doc/xml/firewalld.dbus.xml             |  9 ++++++++
87a48e
 src/firewall/config/__init__.py.in     |  1 +
87a48e
 src/firewall/core/fw.py                | 29 +++++++++++++++++++-------
87a48e
 src/firewall/core/io/firewalld_conf.py | 19 +++++++++++++----
87a48e
 src/firewall/server/config.py          | 23 +++++++++++++-------
87a48e
 src/tests/dbus/firewalld.conf.at       |  2 ++
87a48e
 8 files changed, 82 insertions(+), 21 deletions(-)
87a48e
87a48e
diff --git a/config/firewalld.conf b/config/firewalld.conf
87a48e
index a0556c0bbf5b..3abbc9c998c1 100644
87a48e
--- a/config/firewalld.conf
87a48e
+++ b/config/firewalld.conf
87a48e
@@ -7,10 +7,17 @@ DefaultZone=public
87a48e
 
87a48e
 # Clean up on exit
87a48e
 # If set to no or false the firewall configuration will not get cleaned up
87a48e
-# on exit or stop of firewalld
87a48e
+# on exit or stop of firewalld.
87a48e
 # Default: yes
87a48e
 CleanupOnExit=yes
87a48e
 
87a48e
+# Clean up kernel modules on exit
87a48e
+# If set to yes or true the firewall related kernel modules will be
87a48e
+# unloaded on exit or stop of firewalld. This might attempt to unload
87a48e
+# modules not originally loaded by firewalld.
87a48e
+# Default: no
87a48e
+CleanupModulesOnExit=no
87a48e
+
87a48e
 # Lockdown
87a48e
 # If set to enabled, firewall changes with the D-Bus interface will be limited
87a48e
 # to applications that are listed in the lockdown whitelist.
87a48e
diff --git a/doc/xml/firewalld.conf.xml b/doc/xml/firewalld.conf.xml
87a48e
index 0bf4c2d4d011..dd6ffb214eb3 100644
87a48e
--- a/doc/xml/firewalld.conf.xml
87a48e
+++ b/doc/xml/firewalld.conf.xml
87a48e
@@ -88,6 +88,17 @@
87a48e
 	</listitem>
87a48e
       </varlistentry>
87a48e
 
87a48e
+      <varlistentry>
87a48e
+        <term><option>CleanupModulesOnExit</option></term>
87a48e
+        <listitem>
87a48e
+          <para>
87a48e
+            Setting this option to yes or true unloads all firewall-related
87a48e
+            kernel modules when firewalld is stopped. The default value is no
87a48e
+            or false.
87a48e
+          </para>
87a48e
+        </listitem>
87a48e
+      </varlistentry>
87a48e
+
87a48e
       <varlistentry>
87a48e
 	<term><option>CleanupOnExit</option></term>
87a48e
         <listitem>
87a48e
diff --git a/doc/xml/firewalld.dbus.xml b/doc/xml/firewalld.dbus.xml
87a48e
index d17cb8b6c1ec..466220b40b21 100644
87a48e
--- a/doc/xml/firewalld.dbus.xml
87a48e
+++ b/doc/xml/firewalld.dbus.xml
87a48e
@@ -2798,6 +2798,15 @@
87a48e
               </para>
87a48e
             </listitem>
87a48e
           </varlistentry>
87a48e
+          <varlistentry id="FirewallD1.config.Properties.CleanupModulesOnExit">
87a48e
+            <term>CleanupModulesOnExit - s - (rw)</term>
87a48e
+            <listitem>
87a48e
+              <para>
87a48e
+                Setting this option to yes or true unloads all firewall-related
87a48e
+                kernel modules when firewalld is stopped.
87a48e
+              </para>
87a48e
+            </listitem>
87a48e
+          </varlistentry>
87a48e
           <varlistentry id="FirewallD1.config.Properties.CleanupOnExit">
87a48e
             <term>CleanupOnExit - s - (rw)</term>
87a48e
             <listitem>
87a48e
diff --git a/src/firewall/config/__init__.py.in b/src/firewall/config/__init__.py.in
87a48e
index 0dec7913f694..5d6d769fbf15 100644
87a48e
--- a/src/firewall/config/__init__.py.in
87a48e
+++ b/src/firewall/config/__init__.py.in
87a48e
@@ -125,6 +125,7 @@ FIREWALL_BACKEND_VALUES = [ "nftables", "iptables" ]
87a48e
 FALLBACK_ZONE = "public"
87a48e
 FALLBACK_MINIMAL_MARK = 100
87a48e
 FALLBACK_CLEANUP_ON_EXIT = True
87a48e
+FALLBACK_CLEANUP_MODULES_ON_EXIT = False
87a48e
 FALLBACK_LOCKDOWN = False
87a48e
 FALLBACK_IPV6_RPFILTER = True
87a48e
 FALLBACK_INDIVIDUAL_CALLS = False
87a48e
diff --git a/src/firewall/core/fw.py b/src/firewall/core/fw.py
87a48e
index 3eb54e37ab5c..4171697bdb94 100644
87a48e
--- a/src/firewall/core/fw.py
87a48e
+++ b/src/firewall/core/fw.py
87a48e
@@ -105,12 +105,13 @@ class Firewall(object):
87a48e
         self.__init_vars()
87a48e
 
87a48e
     def __repr__(self):
87a48e
-        return '%s(%r, %r, %r, %r, %r, %r, %r, %r, %r, %r, %r, %r, %r)' % \
87a48e
+        return '%s(%r, %r, %r, %r, %r, %r, %r, %r, %r, %r, %r, %r, %r, %r)' % \
87a48e
             (self.__class__, self.ip4tables_enabled, self.ip6tables_enabled,
87a48e
              self.ebtables_enabled, self._state, self._panic,
87a48e
              self._default_zone, self._module_refcount, self._marks,
87a48e
-             self.cleanup_on_exit, self.ipv6_rpfilter_enabled,
87a48e
-             self.ipset_enabled, self._individual_calls, self._log_denied)
87a48e
+             self.cleanup_on_exit, self.cleanup_modules_on_exit,
87a48e
+             self.ipv6_rpfilter_enabled, self.ipset_enabled,
87a48e
+             self._individual_calls, self._log_denied)
87a48e
 
87a48e
     def __init_vars(self):
87a48e
         self._state = "INIT"
87a48e
@@ -120,6 +121,7 @@ class Firewall(object):
87a48e
         self._marks = [ ]
87a48e
         # fallback settings will be overloaded by firewalld.conf
87a48e
         self.cleanup_on_exit = config.FALLBACK_CLEANUP_ON_EXIT
87a48e
+        self.cleanup_modules_on_exit = config.FALLBACK_CLEANUP_MODULES_ON_EXIT
87a48e
         self.ipv6_rpfilter_enabled = config.FALLBACK_IPV6_RPFILTER
87a48e
         self._individual_calls = config.FALLBACK_INDIVIDUAL_CALLS
87a48e
         self._log_denied = config.FALLBACK_LOG_DENIED
87a48e
@@ -232,6 +234,13 @@ class Firewall(object):
87a48e
                 log.debug1("CleanupOnExit is set to '%s'",
87a48e
                            self.cleanup_on_exit)
87a48e
 
87a48e
+            if self._firewalld_conf.get("CleanupModulesOnExit"):
87a48e
+                value = self._firewalld_conf.get("CleanupModulesOnExit")
87a48e
+                if value is not None and value.lower() in [ "yes", "true" ]:
87a48e
+                    self.cleanup_modules_on_exit = True
87a48e
+                log.debug1("CleanupModulesOnExit is set to '%s'",
87a48e
+                           self.cleanup_modules_on_exit)
87a48e
+
87a48e
             if self._firewalld_conf.get("Lockdown"):
87a48e
                 value = self._firewalld_conf.get("Lockdown")
87a48e
                 if value is not None and value.lower() in [ "yes", "true" ]:
87a48e
@@ -667,11 +676,15 @@ class Firewall(object):
87a48e
         self.__init_vars()
87a48e
 
87a48e
     def stop(self):
87a48e
-        if self.cleanup_on_exit and not self._offline:
87a48e
-            self.flush()
87a48e
-            self.ipset.flush()
87a48e
-            self.set_policy("ACCEPT")
87a48e
-            self.modules_backend.unload_firewall_modules()
87a48e
+        if not self._offline:
87a48e
+            if self.cleanup_on_exit:
87a48e
+                self.flush()
87a48e
+                self.ipset.flush()
87a48e
+                self.set_policy("ACCEPT")
87a48e
+
87a48e
+            if self.cleanup_modules_on_exit:
87a48e
+                log.debug1('Unloading firewall kernel modules')
87a48e
+                self.modules_backend.unload_firewall_modules()
87a48e
 
87a48e
         self.cleanup()
87a48e
 
87a48e
diff --git a/src/firewall/core/io/firewalld_conf.py b/src/firewall/core/io/firewalld_conf.py
87a48e
index 7c7092120676..70258400ef06 100644
87a48e
--- a/src/firewall/core/io/firewalld_conf.py
87a48e
+++ b/src/firewall/core/io/firewalld_conf.py
87a48e
@@ -28,10 +28,11 @@ from firewall import config
87a48e
 from firewall.core.logger import log
87a48e
 from firewall.functions import b2u, u2b, PY2
87a48e
 
87a48e
-valid_keys = [ "DefaultZone", "MinimalMark", "CleanupOnExit", "Lockdown",
87a48e
-               "IPv6_rpfilter", "IndividualCalls", "LogDenied",
87a48e
-               "AutomaticHelpers", "FirewallBackend", "FlushAllOnReload",
87a48e
-               "RFC3964_IPv4", "AllowZoneDrifting" ]
87a48e
+valid_keys = [ "DefaultZone", "MinimalMark", "CleanupOnExit",
87a48e
+               "CleanupModulesOnExit", "Lockdown", "IPv6_rpfilter",
87a48e
+               "IndividualCalls", "LogDenied", "AutomaticHelpers",
87a48e
+               "FirewallBackend", "FlushAllOnReload", "RFC3964_IPv4",
87a48e
+               "AllowZoneDrifting" ]
87a48e
 
87a48e
 class firewalld_conf(object):
87a48e
     def __init__(self, filename):
87a48e
@@ -75,6 +76,7 @@ class firewalld_conf(object):
87a48e
             self.set("DefaultZone", config.FALLBACK_ZONE)
87a48e
             self.set("MinimalMark", str(config.FALLBACK_MINIMAL_MARK))
87a48e
             self.set("CleanupOnExit", "yes" if config.FALLBACK_CLEANUP_ON_EXIT else "no")
87a48e
+            self.set("CleanupModulesOnExit", "yes" if config.FALLBACK_CLEANUP_MODULES_ON_EXIT else "no")
87a48e
             self.set("Lockdown", "yes" if config.FALLBACK_LOCKDOWN else "no")
87a48e
             self.set("IPv6_rpfilter","yes" if config.FALLBACK_IPV6_RPFILTER else "no")
87a48e
             self.set("IndividualCalls", "yes" if config.FALLBACK_INDIVIDUAL_CALLS else "no")
87a48e
@@ -135,6 +137,15 @@ class firewalld_conf(object):
87a48e
                             config.FALLBACK_CLEANUP_ON_EXIT)
87a48e
             self.set("CleanupOnExit", "yes" if config.FALLBACK_CLEANUP_ON_EXIT else "no")
87a48e
 
87a48e
+        # check module cleanup on exit
87a48e
+        value = self.get("CleanupModulesOnExit")
87a48e
+        if not value or value.lower() not in [ "no", "false", "yes", "true" ]:
87a48e
+            if value is not None:
87a48e
+                log.warning("CleanupModulesOnExit '%s' is not valid, using default "
87a48e
+                            "value %s", value if value else '',
87a48e
+                            config.FALLBACK_CLEANUP_MODULES_ON_EXIT)
87a48e
+            self.set("CleanupModulesOnExit", "yes" if config.FALLBACK_CLEANUP_MODULES_ON_EXIT else "no")
87a48e
+
87a48e
         # check lockdown
87a48e
         value = self.get("Lockdown")
87a48e
         if not value or value.lower() not in [ "yes", "true", "no", "false" ]:
87a48e
diff --git a/src/firewall/server/config.py b/src/firewall/server/config.py
87a48e
index 031ef5d1afaa..8815920c6893 100644
87a48e
--- a/src/firewall/server/config.py
87a48e
+++ b/src/firewall/server/config.py
87a48e
@@ -100,6 +100,7 @@ class FirewallDConfig(slip.dbus.service.Object):
87a48e
         dbus_introspection_prepare_properties(self,
87a48e
                                               config.dbus.DBUS_INTERFACE_CONFIG,
87a48e
                                               { "CleanupOnExit": "readwrite",
87a48e
+                                                "CleanupModulesOnExit": "readwrite",
87a48e
                                                 "IPv6_rpfilter": "readwrite",
87a48e
                                                 "Lockdown": "readwrite",
87a48e
                                                 "MinimalMark": "readwrite",
87a48e
@@ -554,9 +555,9 @@ class FirewallDConfig(slip.dbus.service.Object):
87a48e
     @dbus_handle_exceptions
87a48e
     def _get_property(self, prop):
87a48e
         if prop not in [ "DefaultZone", "MinimalMark", "CleanupOnExit",
87a48e
-                         "Lockdown", "IPv6_rpfilter", "IndividualCalls",
87a48e
-                         "LogDenied", "AutomaticHelpers", "FirewallBackend",
87a48e
-                         "FlushAllOnReload", "RFC3964_IPv4",
87a48e
+                         "CleanupModulesOnExit", "Lockdown", "IPv6_rpfilter",
87a48e
+                         "IndividualCalls", "LogDenied", "AutomaticHelpers",
87a48e
+                         "FirewallBackend", "FlushAllOnReload", "RFC3964_IPv4",
87a48e
                          "AllowZoneDrifting" ]:
87a48e
             raise dbus.exceptions.DBusException(
87a48e
                 "org.freedesktop.DBus.Error.InvalidArgs: "
87a48e
@@ -578,6 +579,10 @@ class FirewallDConfig(slip.dbus.service.Object):
87a48e
             if value is None:
87a48e
                 value = "yes" if config.FALLBACK_CLEANUP_ON_EXIT else "no"
87a48e
             return dbus.String(value)
87a48e
+        elif prop == "CleanupModulesOnExit":
87a48e
+            if value is None:
87a48e
+                value = "yes" if config.FALLBACK_CLEANUP_MODULES_ON_EXIT else "no"
87a48e
+            return dbus.String(value)
87a48e
         elif prop == "Lockdown":
87a48e
             if value is None:
87a48e
                 value = "yes" if config.FALLBACK_LOCKDOWN else "no"
87a48e
@@ -623,6 +628,8 @@ class FirewallDConfig(slip.dbus.service.Object):
87a48e
             return dbus.Int32(self._get_property(prop))
87a48e
         elif prop == "CleanupOnExit":
87a48e
             return dbus.String(self._get_property(prop))
87a48e
+        elif prop == "CleanupModulesOnExit":
87a48e
+            return dbus.String(self._get_property(prop))
87a48e
         elif prop == "Lockdown":
87a48e
             return dbus.String(self._get_property(prop))
87a48e
         elif prop == "IPv6_rpfilter":
87a48e
@@ -679,9 +686,9 @@ class FirewallDConfig(slip.dbus.service.Object):
87a48e
         ret = { }
87a48e
         if interface_name == config.dbus.DBUS_INTERFACE_CONFIG:
87a48e
             for x in [ "DefaultZone", "MinimalMark", "CleanupOnExit",
87a48e
-                       "Lockdown", "IPv6_rpfilter", "IndividualCalls",
87a48e
-                       "LogDenied", "AutomaticHelpers", "FirewallBackend",
87a48e
-                       "FlushAllOnReload", "RFC3964_IPv4",
87a48e
+                       "CleanupModulesOnExit", "Lockdown", "IPv6_rpfilter",
87a48e
+                       "IndividualCalls", "LogDenied", "AutomaticHelpers",
87a48e
+                       "FirewallBackend", "FlushAllOnReload", "RFC3964_IPv4",
87a48e
                        "AllowZoneDrifting" ]:
87a48e
                 ret[x] = self._get_property(x)
87a48e
         elif interface_name in [ config.dbus.DBUS_INTERFACE_CONFIG_DIRECT,
87a48e
@@ -706,12 +713,12 @@ class FirewallDConfig(slip.dbus.service.Object):
87a48e
         self.accessCheck(sender)
87a48e
 
87a48e
         if interface_name == config.dbus.DBUS_INTERFACE_CONFIG:
87a48e
-            if property_name in [ "CleanupOnExit", "Lockdown",
87a48e
+            if property_name in [ "CleanupOnExit", "Lockdown", "CleanupModulesOnExit",
87a48e
                                   "IPv6_rpfilter", "IndividualCalls",
87a48e
                                   "LogDenied",
87a48e
                                   "FirewallBackend", "FlushAllOnReload",
87a48e
                                   "RFC3964_IPv4", "AllowZoneDrifting" ]:
87a48e
-                if property_name in [ "CleanupOnExit", "Lockdown",
87a48e
+                if property_name in [ "CleanupOnExit", "Lockdown", "CleanupModulesOnExit",
87a48e
                                       "IPv6_rpfilter", "IndividualCalls" ]:
87a48e
                     if new_value.lower() not in [ "yes", "no",
87a48e
                                                   "true", "false" ]:
87a48e
diff --git a/src/tests/dbus/firewalld.conf.at b/src/tests/dbus/firewalld.conf.at
87a48e
index 9fc5502a8d0b..9a04a3bd491c 100644
87a48e
--- a/src/tests/dbus/firewalld.conf.at
87a48e
+++ b/src/tests/dbus/firewalld.conf.at
87a48e
@@ -17,6 +17,7 @@ dnl Verify defaults over dbus. Should be inline with default firewalld.conf.
87a48e
 DBUS_GETALL([config], [config], 0, [dnl
87a48e
 string "AllowZoneDrifting" : variant string "no"
87a48e
 string "AutomaticHelpers" : variant string "no"
87a48e
+string "CleanupModulesOnExit" : variant string "no"
87a48e
 string "CleanupOnExit" : variant string "no"
87a48e
 string "DefaultZone" : variant string "public"
87a48e
 string "FirewallBackend" : variant string "nftables"
87a48e
@@ -45,6 +46,7 @@ _helper([IPv6_rpfilter], [string:"yes"], [variant string "yes"])
87a48e
 _helper([IndividualCalls], [string:"yes"], [variant string "yes"])
87a48e
 _helper([FirewallBackend], [string:"iptables"], [variant string "iptables"])
87a48e
 _helper([FlushAllOnReload], [string:"no"], [variant string "no"])
87a48e
+_helper([CleanupModulesOnExit], [string:"yes"], [variant string "yes"])
87a48e
 _helper([CleanupOnExit], [string:"yes"], [variant string "yes"])
87a48e
 _helper([RFC3964_IPv4], [string:"no"], [variant string "no"])
87a48e
 _helper([AllowZoneDrifting], [string:"yes"], [variant string "yes"])
87a48e
-- 
87a48e
2.31.1
87a48e