diff --git a/0008-v2.1.0-improvement-nftables-do-not-track-rule-handle.patch b/0008-v2.1.0-improvement-nftables-do-not-track-rule-handle.patch new file mode 100644 index 0000000..11cb584 --- /dev/null +++ b/0008-v2.1.0-improvement-nftables-do-not-track-rule-handle.patch @@ -0,0 +1,66 @@ +From 11ee9b9ed8da78bfc11edffc2c9386efa41be1cf Mon Sep 17 00:00:00 2001 +From: Eric Garver +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 + diff --git a/0009-v2.1.0-improvement-fw-make-set_policy-DROP-more-flex.patch b/0009-v2.1.0-improvement-fw-make-set_policy-DROP-more-flex.patch new file mode 100644 index 0000000..cc01fd2 --- /dev/null +++ b/0009-v2.1.0-improvement-fw-make-set_policy-DROP-more-flex.patch @@ -0,0 +1,203 @@ +From c53dabcb9ca5c6d9ab2b076d961127a67afe8f8f Mon Sep 17 00:00:00 2001 +From: Thomas Haller +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 + diff --git a/0010-v2.1.0-feat-fw-add-ReloadPolicy-option-in-firewalld..patch b/0010-v2.1.0-feat-fw-add-ReloadPolicy-option-in-firewalld..patch new file mode 100644 index 0000000..6bd4f1a --- /dev/null +++ b/0010-v2.1.0-feat-fw-add-ReloadPolicy-option-in-firewalld..patch @@ -0,0 +1,303 @@ +From 67c8a0010ba6244c40e48a93560eb66d91a2ca09 Mon Sep 17 00:00:00 2001 +From: Thomas Haller +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 @@ + + + ++ ++ ++ ++ ++ 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". ++ ++ ++ ++ + + + +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 + diff --git a/firewalld.spec b/firewalld.spec index c0153a3..35a475d 100644 --- a/firewalld.spec +++ b/firewalld.spec @@ -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 - 1.3.4-5 +- feat(fw): add ReloadPolicy option in firewalld.conf + * Mon Jul 01 2024 Eric Garver - 1.3.4-4 - fix(rich): validate service name of rich rule