feat(fw): add ReloadPolicy option in firewalld.conf

Resolves: RHEL-5978
This commit is contained in:
Eric Garver 2024-07-01 10:46:38 -04:00
parent 09e9b4b7ca
commit 9c0f94b6e4
4 changed files with 579 additions and 1 deletions

View File

@ -0,0 +1,66 @@
From 11ee9b9ed8da78bfc11edffc2c9386efa41be1cf Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 18 Dec 2023 18:22:38 -0500
Subject: [PATCH 08/22] v2.1.0: improvement(nftables): do not track rule
handles for policy table
It's not necessary. This table is transient and we simply delete the
entire table when we're done with it.
(cherry picked from commit 119dff1d86f841cd2f33ddbab278bc9257dae7b0)
---
src/firewall/core/nftables.py | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
diff --git a/src/firewall/core/nftables.py b/src/firewall/core/nftables.py
index 3df3fa3c3742..690a5dc067ab 100644
--- a/src/firewall/core/nftables.py
+++ b/src/firewall/core/nftables.py
@@ -386,6 +386,11 @@ class nftables(object):
if verb not in output["nftables"][index]:
continue
+ # don't bother tracking handles for the policy table as we simply
+ # delete the entire table.
+ if TABLE_NAME_POLICY == output["nftables"][index][verb]["rule"]["table"]:
+ continue
+
self.rule_to_handle[rule_key] = output["nftables"][index][verb]["rule"]["handle"]
def set_rule(self, rule, log_denied):
@@ -408,18 +413,8 @@ class nftables(object):
"name": table}}}]
def build_flush_rules(self):
- # Policy is stashed in a separate table that we're _not_ going to
- # flush. As such, we retain the policy rule handles and ref counts.
- saved_rule_to_handle = {}
- saved_rule_ref_count = {}
- for rule in self._build_set_policy_rules_ct_rules(True):
- policy_key = self._get_rule_key(rule)
- if policy_key in self.rule_to_handle:
- saved_rule_to_handle[policy_key] = self.rule_to_handle[policy_key]
- saved_rule_ref_count[policy_key] = self.rule_ref_count[policy_key]
-
- self.rule_to_handle = saved_rule_to_handle
- self.rule_ref_count = saved_rule_ref_count
+ self.rule_to_handle = {}
+ self.rule_ref_count = {}
self.rich_rule_priority_counts = {}
self.policy_priority_counts = {}
self.zone_source_index_cache = {}
@@ -475,11 +470,6 @@ class nftables(object):
rules += self._build_set_policy_rules_ct_rules(True)
elif policy == "ACCEPT":
- for rule in self._build_set_policy_rules_ct_rules(False):
- policy_key = self._get_rule_key(rule)
- if policy_key in self.rule_to_handle:
- rules.append(rule)
-
rules += self._build_delete_table_rules(TABLE_NAME_POLICY)
else:
raise FirewallError(UNKNOWN_ERROR, "not implemented")
--
2.43.5

View File

@ -0,0 +1,203 @@
From c53dabcb9ca5c6d9ab2b076d961127a67afe8f8f Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 11 Aug 2023 18:16:20 +0200
Subject: [PATCH 09/22] v2.1.0: improvement(fw): make set_policy("DROP") more
flexible
We will add a reload-policy via
ReloadPolicy=OUTPUT:{ACCEPT,REJECT,DROP},INPUT:{ACCEPT,REJECT,DROP},FORWARD:{ACCEPT,REJECT,DROP}
Extend set_policy() so that the "DROP" policy can be overridden.
(cherry picked from commit e3bb468ff469373d193398b471a59f7ab7d29f27)
---
src/firewall/core/ebtables.py | 2 +-
src/firewall/core/fw.py | 27 +++++++++++++---
src/firewall/core/ipXtables.py | 11 +++++--
src/firewall/core/nftables.py | 56 ++++++++++++++++++++++++----------
4 files changed, 72 insertions(+), 24 deletions(-)
diff --git a/src/firewall/core/ebtables.py b/src/firewall/core/ebtables.py
index c1c0b8587a5c..f059975724a5 100644
--- a/src/firewall/core/ebtables.py
+++ b/src/firewall/core/ebtables.py
@@ -237,7 +237,7 @@ class ebtables(object):
rules.append(["-t", table, flag])
return rules
- def build_set_policy_rules(self, policy):
+ def build_set_policy_rules(self, policy, policy_details):
rules = []
_policy = "DROP" if policy == "PANIC" else policy
for table in BUILT_IN_CHAINS.keys():
diff --git a/src/firewall/core/fw.py b/src/firewall/core/fw.py
index f1bc124b9443..ccec875f3c3c 100644
--- a/src/firewall/core/fw.py
+++ b/src/firewall/core/fw.py
@@ -983,7 +983,18 @@ class Firewall(object):
if use_transaction is None:
transaction.execute(True)
- def set_policy(self, policy, use_transaction=None):
+ def _set_policy_build_rules(self, backend, policy, policy_details=None):
+ assert policy in ("ACCEPT", "DROP", "PANIC")
+ if policy_details is None:
+ dp = "ACCEPT" if policy == "ACCEPT" else "DROP"
+ policy_details = {
+ "INPUT": dp,
+ "OUTPUT": dp,
+ "FORWARD": dp,
+ }
+ return backend.build_set_policy_rules(policy, policy_details)
+
+ def set_policy(self, policy, policy_details=None, use_transaction=None):
if use_transaction is None:
transaction = FirewallTransaction(self)
else:
@@ -992,7 +1003,7 @@ class Firewall(object):
log.debug1("Setting policy to '%s'", policy)
for backend in self.enabled_backends():
- rules = backend.build_set_policy_rules(policy)
+ rules = self._set_policy_build_rules(backend, policy, policy_details)
transaction.add_rules(backend, rules)
if use_transaction is None:
@@ -1224,13 +1235,19 @@ class Firewall(object):
# for the old backend that was set to DROP above.
if not self._panic and old_firewall_backend != self._firewall_backend:
if old_firewall_backend == "nftables":
- for rule in self.nftables_backend.build_set_policy_rules("ACCEPT"):
+ for rule in self._set_policy_build_rules(
+ self.nftables_backend, "ACCEPT"
+ ):
self.nftables_backend.set_rule(rule, self._log_denied)
else:
- for rule in self.ip4tables_backend.build_set_policy_rules("ACCEPT"):
+ for rule in self._set_policy_build_rules(
+ self.ip4tables_backend, "ACCEPT"
+ ):
self.ip4tables_backend.set_rule(rule, self._log_denied)
if self.ip6tables_enabled:
- for rule in self.ip6tables_backend.build_set_policy_rules("ACCEPT"):
+ for rule in self._set_policy_build_rules(
+ self.ip6tables_backend, "ACCEPT"
+ ):
self.ip6tables_backend.set_rule(rule, self._log_denied)
if start_exception:
diff --git a/src/firewall/core/ipXtables.py b/src/firewall/core/ipXtables.py
index e05a2bd4d7ed..1a0cea7a3b4e 100644
--- a/src/firewall/core/ipXtables.py
+++ b/src/firewall/core/ipXtables.py
@@ -578,7 +578,7 @@ class ip4tables(object):
rules.append(["-t", table, flag])
return rules
- def build_set_policy_rules(self, policy):
+ def build_set_policy_rules(self, policy, policy_details):
rules = []
_policy = "DROP" if policy == "PANIC" else policy
for table in BUILT_IN_CHAINS.keys():
@@ -587,7 +587,14 @@ class ip4tables(object):
if table == "nat":
continue
for chain in BUILT_IN_CHAINS[table]:
- rules.append(["-t", table, "-P", chain, _policy])
+ if table == "filter":
+ p = policy_details[chain]
+ if p == "REJECT":
+ rules.append(["-t", table, "-A", chain, "-j", "REJECT"])
+ p = "DROP"
+ else:
+ p = _policy
+ rules.append(["-t", table, "-P", chain, p])
return rules
def supported_icmp_types(self, ipv=None):
diff --git a/src/firewall/core/nftables.py b/src/firewall/core/nftables.py
index 690a5dc067ab..e9816147ef8e 100644
--- a/src/firewall/core/nftables.py
+++ b/src/firewall/core/nftables.py
@@ -421,20 +421,17 @@ class nftables(object):
return self._build_delete_table_rules(TABLE_NAME)
- def _build_set_policy_rules_ct_rules(self, enable):
+ def _build_set_policy_rules_ct_rule(self, enable, hook):
add_del = { True: "add", False: "delete" }[enable]
- rules = []
- for hook in ["input", "forward", "output"]:
- rules.append({add_del: {"rule": {"family": "inet",
- "table": TABLE_NAME_POLICY,
- "chain": "%s_%s" % ("filter", hook),
- "expr": [{"match": {"left": {"ct": {"key": "state"}},
- "op": "in",
- "right": {"set": ["established", "related"]}}},
- {"accept": None}]}}})
- return rules
-
- def build_set_policy_rules(self, policy):
+ return {add_del: {"rule": {"family": "inet",
+ "table": TABLE_NAME_POLICY,
+ "chain": "%s_%s" % ("filter", hook),
+ "expr": [{"match": {"left": {"ct": {"key": "state"}},
+ "op": "in",
+ "right": {"set": ["established", "related"]}}},
+ {"accept": None}]}}}
+
+ def build_set_policy_rules(self, policy, policy_details):
# Policy is not exposed to the user. It's only to make sure we DROP
# packets while reloading and for panic mode. As such, using hooks with
# a higher priority than our base chains is sufficient.
@@ -459,16 +456,43 @@ class nftables(object):
# To drop everything except existing connections we use
# "filter" because it occurs _after_ conntrack.
- for hook in ["input", "forward", "output"]:
+ for hook in ("INPUT", "FORWARD", "OUTPUT"):
+ d_policy = policy_details[hook]
+ assert d_policy in ("ACCEPT", "REJECT", "DROP")
+ hook = hook.lower()
+ chain_name = f"filter_{hook}"
+
rules.append({"add": {"chain": {"family": "inet",
"table": TABLE_NAME_POLICY,
- "name": "%s_%s" % ("filter", hook),
+ "name": chain_name,
"type": "filter",
"hook": hook,
"prio": 0 + NFT_HOOK_OFFSET - 1,
"policy": "drop"}}})
- rules += self._build_set_policy_rules_ct_rules(True)
+ rules.append(self._build_set_policy_rules_ct_rule(True, hook))
+
+ if d_policy == "ACCEPT":
+ expr_fragment = {"accept": None}
+ elif d_policy == "DROP":
+ expr_fragment = {"drop": None}
+ else:
+ expr_fragment = {
+ "reject": {"type": "icmpx", "expr": "admin-prohibited"}
+ }
+
+ rules.append(
+ {
+ "add": {
+ "rule": {
+ "family": "inet",
+ "table": TABLE_NAME_POLICY,
+ "chain": chain_name,
+ "expr": [expr_fragment],
+ }
+ }
+ }
+ )
elif policy == "ACCEPT":
rules += self._build_delete_table_rules(TABLE_NAME_POLICY)
else:
--
2.43.5

View File

@ -0,0 +1,303 @@
From 67c8a0010ba6244c40e48a93560eb66d91a2ca09 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Mon, 14 Aug 2023 14:53:55 +0200
Subject: [PATCH 10/22] v2.1.0: feat(fw): add ReloadPolicy option in
firewalld.conf
One interesting aspect is that during `firewall-cmd --reload`, the code
first sets the policy to "DROP", before reloading "firewalld.conf". That
means, changing the value only takes effect after the next reload. But
that seems expected as we set the policy before starting to reload.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2149039
(cherry picked from commit 0019371a8f42d376ac9cce79cc5e1e7d2049f021)
---
config/firewalld.conf | 8 +++
doc/xml/firewalld.conf.xml | 16 ++++++
src/firewall/config/__init__.py.in | 1 +
src/firewall/core/fw.py | 13 ++++-
src/firewall/core/io/firewalld_conf.py | 56 ++++++++++++++++++++-
src/tests/features/features.at | 1 +
src/tests/features/reloadpolicy.at | 12 +++++
src/tests/unit/test_firewalld_conf.py | 68 ++++++++++++++++++++++++++
8 files changed, 172 insertions(+), 3 deletions(-)
create mode 100644 src/tests/features/reloadpolicy.at
create mode 100644 src/tests/unit/test_firewalld_conf.py
diff --git a/config/firewalld.conf b/config/firewalld.conf
index f8caf11c8a86..7a0be1ff1b76 100644
--- a/config/firewalld.conf
+++ b/config/firewalld.conf
@@ -66,6 +66,14 @@ FirewallBackend=nftables
# Default: yes
FlushAllOnReload=yes
+# ReloadPolicy
+# Policy during reload. By default all traffic except for established
+# connections is dropped while the rules are updated. Set to "DROP", "REJECT"
+# or "ACCEPT". Alternatively, specify it per table, like
+# "OUTPUT:ACCEPT,INPUT:DROP,FORWARD:REJECT".
+# Default: ReloadPolicy=INPUT:DROP,FORWARD:DROP,OUTPUT:DROP
+ReloadPolicy=INPUT:DROP,FORWARD:DROP,OUTPUT:DROP
+
# RFC3964_IPv4
# As per RFC 3964, filter IPv6 traffic with 6to4 destination addresses that
# correspond to IPv4 addresses that should not be routed over the public
diff --git a/doc/xml/firewalld.conf.xml b/doc/xml/firewalld.conf.xml
index e4312acc8e1c..022569ccf502 100644
--- a/doc/xml/firewalld.conf.xml
+++ b/doc/xml/firewalld.conf.xml
@@ -195,6 +195,22 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>ReloadPolicy</option></term>
+ <listitem>
+ <para>
+ The policy during reload. By default, all traffic except
+ established connections is dropped while reloading the
+ firewall rules. This can be overridden for INPUT, FORWARD
+ and OUTPUT. The accepted values are "DROP", "REJECT" and
+ "ACCEPT", which then applies to all tables. Alternatively,
+ the policy can be specified per table, like
+ "INPUT:REJECT,FORWARD:DROP,OUTPUT:ACCEPT".
+ Defaults to "INPUT:DROP,FORWARD:DROP,OUTPUT:DROP".
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>RFC3964_IPv4</option></term>
<listitem>
diff --git a/src/firewall/config/__init__.py.in b/src/firewall/config/__init__.py.in
index d982384a0382..da1e31e10e58 100644
--- a/src/firewall/config/__init__.py.in
+++ b/src/firewall/config/__init__.py.in
@@ -133,5 +133,6 @@ FALLBACK_LOG_DENIED = "off"
FALLBACK_AUTOMATIC_HELPERS = "no"
FALLBACK_FIREWALL_BACKEND = "nftables"
FALLBACK_FLUSH_ALL_ON_RELOAD = True
+FALLBACK_RELOAD_POLICY = "INPUT:DROP,FORWARD:DROP,OUTPUT:DROP"
FALLBACK_RFC3964_IPV4 = True
FALLBACK_ALLOW_ZONE_DRIFTING = False
diff --git a/src/firewall/core/fw.py b/src/firewall/core/fw.py
index ccec875f3c3c..ac13be122b66 100644
--- a/src/firewall/core/fw.py
+++ b/src/firewall/core/fw.py
@@ -1000,7 +1000,13 @@ class Firewall(object):
else:
transaction = use_transaction
- log.debug1("Setting policy to '%s'", policy)
+ log.debug1(
+ "Setting policy to '%s'%s",
+ policy,
+ f" (ReloadPolicy={firewalld_conf._unparse_reload_policy(policy_details)})"
+ if policy == "DROP"
+ else "",
+ )
for backend in self.enabled_backends():
rules = self._set_policy_build_rules(backend, policy, policy_details)
@@ -1146,7 +1152,10 @@ class Firewall(object):
_ipset_objs.append(self.ipset.get_ipset(_name))
if not _panic:
- self.set_policy("DROP")
+ reload_policy = firewalld_conf._parse_reload_policy(
+ self._firewalld_conf.get("ReloadPolicy")
+ )
+ self.set_policy("DROP", policy_details=reload_policy)
self.flush()
self.cleanup()
diff --git a/src/firewall/core/io/firewalld_conf.py b/src/firewall/core/io/firewalld_conf.py
index b907c5b1e60b..d2879b319d1f 100644
--- a/src/firewall/core/io/firewalld_conf.py
+++ b/src/firewall/core/io/firewalld_conf.py
@@ -31,7 +31,7 @@ valid_keys = [ "DefaultZone", "MinimalMark", "CleanupOnExit",
"CleanupModulesOnExit", "Lockdown", "IPv6_rpfilter",
"IndividualCalls", "LogDenied", "AutomaticHelpers",
"FirewallBackend", "FlushAllOnReload", "RFC3964_IPv4",
- "AllowZoneDrifting" ]
+ "AllowZoneDrifting", "ReloadPolicy" ]
class firewalld_conf(object):
def __init__(self, filename):
@@ -77,6 +77,7 @@ class firewalld_conf(object):
self.set("AutomaticHelpers", config.FALLBACK_AUTOMATIC_HELPERS)
self.set("FirewallBackend", config.FALLBACK_FIREWALL_BACKEND)
self.set("FlushAllOnReload", "yes" if config.FALLBACK_FLUSH_ALL_ON_RELOAD else "no")
+ self.set("ReloadPolicy", config.FALLBACK_RELOAD_POLICY)
self.set("RFC3964_IPv4", "yes" if config.FALLBACK_RFC3964_IPV4 else "no")
self.set("AllowZoneDrifting", "yes" if config.FALLBACK_ALLOW_ZONE_DRIFTING else "no")
@@ -208,6 +209,17 @@ class firewalld_conf(object):
config.FALLBACK_FLUSH_ALL_ON_RELOAD)
self.set("FlushAllOnReload", str(config.FALLBACK_FLUSH_ALL_ON_RELOAD))
+ value = self.get("ReloadPolicy")
+ try:
+ value = self._parse_reload_policy(value)
+ except ValueError:
+ log.warning(
+ "ReloadPolicy '%s' is not valid, using default value '%s'",
+ value,
+ config.FALLBACK_RELOAD_POLICY,
+ )
+ self.set("ReloadPolicy", config.FALLBACK_RELOAD_POLICY)
+
value = self.get("RFC3964_IPv4")
if not value or value.lower() not in [ "yes", "true", "no", "false" ]:
if value is not None:
@@ -330,3 +342,45 @@ class firewalld_conf(object):
raise IOError("Failed to create '%s': %s" % (self.filename, msg))
else:
os.chmod(self.filename, 0o600)
+
+ @staticmethod
+ def _parse_reload_policy(value):
+ valid = True
+ result = {
+ "INPUT": "DROP",
+ "FORWARD": "DROP",
+ "OUTPUT": "DROP",
+ }
+ if value:
+ value = value.strip()
+ v = value.upper()
+ if v in ("ACCEPT", "REJECT", "DROP"):
+ for k in result:
+ result[k] = v
+ else:
+ for a in value.replace(";", ",").split(","):
+ a = a.strip()
+ if not a:
+ continue
+ a2 = a.replace("=", ":").split(":", 2)
+ if len(a2) != 2:
+ valid = False
+ continue
+ k = a2[0].strip().upper()
+ if k not in result:
+ valid = False
+ continue
+ v = a2[1].strip().upper()
+ if v not in ("ACCEPT", "REJECT", "DROP"):
+ valid = False
+ continue
+ result[k] = v
+
+ if not valid:
+ raise ValueError("Invalid ReloadPolicy")
+
+ return result
+
+ @staticmethod
+ def _unparse_reload_policy(value):
+ return ",".join(f"{k}:{v}" for k, v in value.items())
diff --git a/src/tests/features/features.at b/src/tests/features/features.at
index f59baea1cd70..065cb2872e88 100644
--- a/src/tests/features/features.at
+++ b/src/tests/features/features.at
@@ -20,3 +20,4 @@ m4_include([features/startup_failsafe.at])
m4_include([features/ipset.at])
m4_include([features/reset_defaults.at])
m4_include([features/iptables_no_flush_on_shutdown.at])
+m4_include([features/reloadpolicy.at])
diff --git a/src/tests/features/reloadpolicy.at b/src/tests/features/reloadpolicy.at
new file mode 100644
index 000000000000..fea1aa26aab4
--- /dev/null
+++ b/src/tests/features/reloadpolicy.at
@@ -0,0 +1,12 @@
+FWD_START_TEST([check ReloadPolicy])
+AT_KEYWORDS(reloadpolicy rhbz2149039)
+
+AT_CHECK([sed -i 's/^ReloadPolicy=.*/ReloadPolicy=INPUT:REJECT,FORWARD:ACCEPT/' ./firewalld.conf])
+dnl call RELOAD twice, to see more action about the ReloadPolicy.
+FWD_RELOAD()
+FWD_RELOAD()
+
+AT_CHECK([sed -i 's/^ReloadPolicy=.*/ReloadPolicy=REJECT/' ./firewalld.conf])
+FWD_RELOAD()
+
+FWD_END_TEST()
diff --git a/src/tests/unit/test_firewalld_conf.py b/src/tests/unit/test_firewalld_conf.py
new file mode 100644
index 000000000000..0ce1fd279f91
--- /dev/null
+++ b/src/tests/unit/test_firewalld_conf.py
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import firewall.core.io.firewalld_conf
+import firewall.config
+
+
+def test_reload_policy():
+ def t(value, expected_valid=True, **kw):
+
+ expected = {
+ "INPUT": "DROP",
+ "FORWARD": "DROP",
+ "OUTPUT": "DROP",
+ }
+ for k, v in kw.items():
+ assert k in expected
+ expected[k] = v
+
+ try:
+ parsed = (
+ firewall.core.io.firewalld_conf.firewalld_conf._parse_reload_policy(
+ value
+ )
+ )
+ except ValueError:
+ assert not expected_valid
+ return
+
+ assert parsed == expected
+ assert expected_valid
+
+ unparsed = (
+ firewall.core.io.firewalld_conf.firewalld_conf._unparse_reload_policy(
+ parsed
+ )
+ )
+ parsed2 = firewall.core.io.firewalld_conf.firewalld_conf._parse_reload_policy(
+ unparsed
+ )
+ assert parsed2 == parsed
+
+ t(None)
+ t("")
+ t(" ")
+ t(" input: ACCept ", INPUT="ACCEPT")
+ t(
+ "forward:DROP, forward : REJEct; input: ACCept ",
+ INPUT="ACCEPT",
+ FORWARD="REJECT",
+ )
+ t(" accept ", INPUT="ACCEPT", FORWARD="ACCEPT", OUTPUT="ACCEPT")
+ t("REJECT", INPUT="REJECT", FORWARD="REJECT", OUTPUT="REJECT")
+ t("forward=REJECT", FORWARD="REJECT")
+ t("forward=REJECT , input=accept", FORWARD="REJECT", INPUT="ACCEPT")
+ t("forward=REJECT , xinput=accept", expected_valid=False)
+ t("forward=REJECT, ACCEPT", expected_valid=False)
+
+ def _norm(reload_policy):
+ parsed = firewall.core.io.firewalld_conf.firewalld_conf._parse_reload_policy(
+ reload_policy
+ )
+ return firewall.core.io.firewalld_conf.firewalld_conf._unparse_reload_policy(
+ parsed
+ )
+
+ assert firewall.config.FALLBACK_RELOAD_POLICY == _norm(
+ firewall.config.FALLBACK_RELOAD_POLICY
+ )
--
2.43.5

View File

@ -1,7 +1,7 @@
Summary: A firewall daemon with D-Bus interface providing a dynamic firewall
Name: firewalld
Version: 1.3.4
Release: 4%{?dist}
Release: 5%{?dist}
URL: http://www.firewalld.org
License: GPLv2+
Source0: https://github.com/firewalld/firewalld/releases/download/v%{version}/firewalld-%{version}.tar.bz2
@ -12,6 +12,9 @@ Patch4: 0004-v1.4.0-test-direct-avoid-iptables-flush-if-using-nft.patch
Patch5: 0005-v2.0.0-feat-service-add-OpenTelemetry-OTLP-service.patch
Patch6: 0006-v2.1.0-feat-icmp-add-ICMPv6-Multicast-Listener-Disco.patch
Patch7: 0007-v2.1.0-fix-rich-validate-service-name-of-rich-rule.patch
Patch8: 0008-v2.1.0-improvement-nftables-do-not-track-rule-handle.patch
Patch9: 0009-v2.1.0-improvement-fw-make-set_policy-DROP-more-flex.patch
Patch10: 0010-v2.1.0-feat-fw-add-ReloadPolicy-option-in-firewalld..patch
BuildArch: noarch
BuildRequires: autoconf
BuildRequires: automake
@ -235,6 +238,9 @@ rm -rf %{buildroot}%{_datadir}/firewalld/testsuite
%{_mandir}/man1/firewall-config*.1*
%changelog
* Mon Jul 01 2024 Eric Garver <egarver@redhat.com> - 1.3.4-5
- feat(fw): add ReloadPolicy option in firewalld.conf
* Mon Jul 01 2024 Eric Garver <egarver@redhat.com> - 1.3.4-4
- fix(rich): validate service name of rich rule