import CS git firewalld-1.3.4-19.el9_8

This commit is contained in:
AlmaLinux RelEng Bot 2026-08-04 16:10:19 -04:00
parent 785c2e7cc1
commit eb5673aa04
22 changed files with 2111 additions and 1 deletions

View File

@ -0,0 +1,42 @@
From 21c9e9ad3811a9679e494a1fe32834edf96393af Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Fri, 13 Sep 2024 13:38:07 -0400
Subject: [PATCH 49/70] v2.3.0: fix(policy): timeout argument for rich rules
This is inconsequential, but noticed which looking at other changes.
(cherry picked from commit 24f0e4ffc9dead83f178d4fdced6cd08852c6d9e)
---
src/firewall/core/fw_policy.py | 2 +-
src/firewall/core/fw_zone.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index ff6ac07a2dc1..0a3c37224882 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -170,7 +170,7 @@ class FirewallPolicy(object):
# stupid wrappers to convert rich rule string to rich rule object
from firewall.core.rich import Rich_Rule
def add_rule_wrapper(policy, rule_str, timeout=0, sender=None):
- self.add_rule(policy, Rich_Rule(rule_str=rule_str), timeout=0, sender=sender)
+ self.add_rule(policy, Rich_Rule(rule_str=rule_str), timeout=timeout, sender=sender)
def remove_rule_wrapper(policy, rule_str):
self.remove_rule(policy, Rich_Rule(rule_str=rule_str))
diff --git a/src/firewall/core/fw_zone.py b/src/firewall/core/fw_zone.py
index cdf080895e50..6c659047b97d 100644
--- a/src/firewall/core/fw_zone.py
+++ b/src/firewall/core/fw_zone.py
@@ -343,7 +343,7 @@ class FirewallZone(object):
def set_config_with_settings_dict(self, zone, settings, sender):
# stupid wrappers to convert rich rule string to rich rule object
def add_rule_wrapper(zone, rule_str, timeout=0, sender=None):
- self.add_rule(zone, Rich_Rule(rule_str=rule_str), timeout=0, sender=sender)
+ self.add_rule(zone, Rich_Rule(rule_str=rule_str), timeout=timeout, sender=sender)
def remove_rule_wrapper(zone, rule_str):
self.remove_rule(zone, Rich_Rule(rule_str=rule_str))
--
2.52.0

View File

@ -0,0 +1,30 @@
From 697ab1154b57fc875aa87d9407a3d123b324731d Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Tue, 6 Jan 2026 13:13:44 -0500
Subject: [PATCH 50/70] v2.5.0: test(functions): fix macro
CHECK_NFT_CT_HELPER()
It never worked!
Fixes: 32c2497f6ec0 ("test: add macro CHECK_NFT_CT_HELPER()")
(cherry picked from commit eca5890a1ac596dd3ff08f6446de0b68427dffc9)
---
src/tests/functions.at | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/tests/functions.at b/src/tests/functions.at
index df3fff6ad4b9..fa0c961fb574 100644
--- a/src/tests/functions.at
+++ b/src/tests/functions.at
@@ -647,7 +647,7 @@ m4_define([CHECK_LOG_AUDIT], [
m4_define([CHECK_NFT_CT_HELPER], [
m4_if(nftables, FIREWALL_BACKEND, [
NS_CHECK([nft add table inet firewalld_check_ct_helper])
- AT_SKIP_IF([! NS_CMD([nft add ct helper inet firewalld helper-ftp-tcp { type \"ftp\" protocol tcp \; } >/dev/null 2>&1])])
+ AT_SKIP_IF([! NS_CMD([nft add ct helper inet firewalld_check_ct_helper helper-ftp-tcp { type \"ftp\" protocol tcp \; } >/dev/null 2>&1])])
NS_CHECK([nft delete table inet firewalld_check_ct_helper])
])
])
--
2.52.0

View File

@ -0,0 +1,60 @@
From a21b62942819c4fd5d83fad49e45d0033954aa24 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 14:18:42 -0500
Subject: [PATCH 51/70] v2.5.0: chore(fw_policy): add utility functions to
support timeouts
(cherry picked from commit 2a14e41b153c397cce3379be4e7ee2651c8d2a79)
---
src/firewall/core/fw_policy.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index 0a3c37224882..444d84fe9023 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -2,6 +2,8 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
+from gi.repository import GLib
+
import copy
from firewall.core.logger import log
@@ -23,6 +25,7 @@ class FirewallPolicy(object):
self._fw = fw
self._chains = { }
self._policies = { }
+ self._timeouts = {}
def __repr__(self):
return '%s(%r, %r)' % (self.__class__, self._chains, self._policies)
@@ -30,6 +33,8 @@ class FirewallPolicy(object):
def cleanup(self):
self._chains.clear()
self._policies.clear()
+ for _id in self._timeouts:
+ self.removeTimeout(_id)
# transaction
@@ -217,6 +222,15 @@ class FirewallPolicy(object):
else: # bool
setting_to_fn[key][0](policy, timeout=0, sender=sender)
+ def addTimeout(self, tag, _id):
+ if _id not in self._timeouts:
+ self._timeouts[_id] = tag
+
+ def removeTimeout(self, _id):
+ if _id in self._timeouts:
+ GLib.source_remove(self._timeouts[_id])
+ del self._timeouts[_id]
+
# ingress zones
def check_ingress_zone(self, zone):
--
2.52.0

View File

@ -0,0 +1,77 @@
From 1f650ad8b02f761732305c5ffc9ae84d774bb48a Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 14:19:23 -0500
Subject: [PATCH 52/70] v2.5.0: chore(zone): service: move timeouts to policy
(cherry picked from commit 248d69433f236dd67f9104ace8baf61298b044eb)
---
src/firewall/core/fw_policy.py | 8 ++++++++
src/firewall/server/firewalld.py | 12 +-----------
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index 444d84fe9023..8087f4bf9509 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -556,6 +556,12 @@ class FirewallPolicy(object):
if _obj.applied:
self._service(True, _policy, service, transaction)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(
+ timeout, self.remove_service, _policy, service
+ )
+ self.addTimeout(tag, ("service", _policy, service))
+
self.__register_service(_obj, service_id, timeout, sender)
transaction.add_fail(self.__unregister_service, _obj, service_id)
@@ -587,6 +593,8 @@ class FirewallPolicy(object):
if _obj.applied:
self._service(False, _policy, service, transaction)
+ self.removeTimeout(("service", _policy, service))
+
transaction.add_post(self.__unregister_service, _obj, service_id)
if use_transaction is None:
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index fc85d3e0c359..58c773732953 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -1553,13 +1553,6 @@ class FirewallD(DbusServiceObject):
# SERVICES
- @dbus_handle_exceptions
- def disableTimedService(self, zone, service):
- log.debug1("zone.disableTimedService('%s', '%s')" % (zone, service))
- del self._timeouts[zone][service]
- self.fw.zone.remove_service(zone, service)
- self.ServiceRemoved(zone, service)
-
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG)
@dbus_service_method(config.dbus.DBUS_INTERFACE_ZONE, in_signature='ssi',
out_signature='s')
@@ -1575,9 +1568,7 @@ class FirewallD(DbusServiceObject):
_zone = self.fw.zone.add_service(zone, service, timeout, sender)
if timeout > 0:
- tag = GLib.timeout_add_seconds(timeout, self.disableTimedService,
- _zone, service)
- self.addTimeout(_zone, service, tag)
+ GLib.timeout_add_seconds(timeout, self.ServiceRemoved, _zone, service)
self.ServiceAdded(_zone, service, timeout)
return _zone
@@ -1595,7 +1586,6 @@ class FirewallD(DbusServiceObject):
_zone = self.fw.zone.remove_service(zone, service)
- self.removeTimeout(_zone, service)
self.ServiceRemoved(_zone, service)
return _zone
--
2.52.0

View File

@ -0,0 +1,78 @@
From 53686874a4dfb7cf2ec5a7a31969e8c19e64d1c4 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 14:24:36 -0500
Subject: [PATCH 53/70] v2.5.0: chore(zone): port: move timeouts to policy
(cherry picked from commit 5db0925a9478ce5f6dd719f34a0da3c7185d4647)
---
src/firewall/core/fw_policy.py | 8 ++++++++
src/firewall/server/firewalld.py | 13 +------------
2 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index 8087f4bf9509..733758d7d3f7 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -690,6 +690,12 @@ class FirewallPolicy(object):
port_id = self.__port_id(range, protocol)
transaction.add_post(self.__unregister_port, _obj, port_id)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(
+ timeout, self.remove_port, _policy, port, protocol
+ )
+ self.addTimeout(tag, ("port", _policy, port, protocol))
+
if use_transaction is None:
transaction.execute(True)
@@ -734,6 +740,8 @@ class FirewallPolicy(object):
port_id = self.__port_id(range, protocol)
transaction.add_post(self.__unregister_port, _obj, port_id)
+ self.removeTimeout(("port", _policy, port, protocol))
+
if use_transaction is None:
transaction.execute(True)
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index 58c773732953..939fb687a7af 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -1627,14 +1627,6 @@ class FirewallD(DbusServiceObject):
# PORTS
- @dbus_handle_exceptions
- def disableTimedPort(self, zone, port, protocol):
- log.debug1("zone.disableTimedPort('%s', '%s', '%s')" % \
- (zone, port, protocol))
- del self._timeouts[zone][(port, protocol)]
- self.fw.zone.remove_port(zone, port, protocol)
- self.PortRemoved(zone, port, protocol)
-
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG)
@dbus_service_method(config.dbus.DBUS_INTERFACE_ZONE, in_signature='sssi',
out_signature='s')
@@ -1651,9 +1643,7 @@ class FirewallD(DbusServiceObject):
_zone = self.fw.zone.add_port(zone, port, protocol, timeout, sender)
if timeout > 0:
- tag = GLib.timeout_add_seconds(timeout, self.disableTimedPort,
- _zone, port, protocol)
- self.addTimeout(_zone, (port, protocol), tag)
+ GLib.timeout_add_seconds(timeout, self.PortRemoved, _zone, port, protocol)
self.PortAdded(_zone, port, protocol, timeout)
return _zone
@@ -1672,7 +1662,6 @@ class FirewallD(DbusServiceObject):
self.accessCheck(sender)
_zone= self.fw.zone.remove_port(zone, port, protocol)
- self.removeTimeout(_zone, (port, protocol))
self.PortRemoved(_zone, port, protocol)
return _zone
--
2.52.0

View File

@ -0,0 +1,81 @@
From cbdfc33f078818127e4be2e510b665ca1f0f6bda Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 15:06:56 -0500
Subject: [PATCH 54/70] v2.5.0: chore(zone): source_port: move timeouts to
policy
(cherry picked from commit 41a2573afefb4d20801b27e3862293c0e06a344d)
---
src/firewall/core/fw_policy.py | 8 ++++++++
src/firewall/server/firewalld.py | 15 +++------------
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index 733758d7d3f7..ee652d892d4a 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -886,6 +886,12 @@ class FirewallPolicy(object):
port_id = self.__source_port_id(range, protocol)
transaction.add_post(self.__unregister_source_port, _obj, port_id)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(
+ timeout, self.remove_source_port, _policy, port, protocol
+ )
+ self.addTimeout(tag, ("source_port", _policy, port, protocol))
+
if use_transaction is None:
transaction.execute(True)
@@ -930,6 +936,8 @@ class FirewallPolicy(object):
port_id = self.__source_port_id(range, protocol)
transaction.add_post(self.__unregister_source_port, _obj, port_id)
+ self.removeTimeout(("source_port", _policy, port, protocol))
+
if use_transaction is None:
transaction.execute(True)
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index 939fb687a7af..75fa486f0f92 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -1787,14 +1787,6 @@ class FirewallD(DbusServiceObject):
# SOURCE PORTS
- @dbus_handle_exceptions
- def disableTimedSourcePort(self, zone, port, protocol):
- log.debug1("zone.disableTimedSourcePort('%s', '%s', '%s')" % \
- (zone, port, protocol))
- del self._timeouts[zone][("sport", port, protocol)]
- self.fw.zone.remove_source_port(zone, port, protocol)
- self.SourcePortRemoved(zone, port, protocol)
-
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG)
@dbus_service_method(config.dbus.DBUS_INTERFACE_ZONE, in_signature='sssi',
out_signature='s')
@@ -1812,9 +1804,9 @@ class FirewallD(DbusServiceObject):
sender)
if timeout > 0:
- tag = GLib.timeout_add_seconds(timeout, self.disableTimedSourcePort,
- _zone, port, protocol)
- self.addTimeout(_zone, ("sport", port, protocol), tag)
+ GLib.timeout_add_seconds(
+ timeout, self.SourcePortRemoved, _zone, port, protocol
+ )
self.SourcePortAdded(_zone, port, protocol, timeout)
return _zone
@@ -1833,7 +1825,6 @@ class FirewallD(DbusServiceObject):
self.accessCheck(sender)
_zone= self.fw.zone.remove_source_port(zone, port, protocol)
- self.removeTimeout(_zone, ("sport", port, protocol))
self.SourcePortRemoved(_zone, port, protocol)
return _zone
--
2.52.0

View File

@ -0,0 +1,91 @@
From c53903f8b42673451a22992a4b1199ad5e554533 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 15:03:21 -0500
Subject: [PATCH 55/70] v2.5.0: chore(zone): forward_port: move timeouts to
policy
(cherry picked from commit b7f543d71b25218eb6cdabf78fdb678507201400)
---
src/firewall/core/fw_policy.py | 18 ++++++++++++++++++
src/firewall/server/firewalld.py | 15 +++------------
2 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index ee652d892d4a..70ca2ecf20d3 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -1068,6 +1068,20 @@ class FirewallPolicy(object):
self._forward_port(True, _policy, transaction, port, protocol,
toport, toaddr)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(
+ timeout,
+ self.remove_forward_port,
+ _policy,
+ port,
+ protocol,
+ toport,
+ toaddr,
+ )
+ self.addTimeout(
+ tag, ("forward_port", _policy, port, protocol, toport, toaddr)
+ )
+
self.__register_forward_port(_obj, forward_id, timeout, sender)
transaction.add_fail(self.__unregister_forward_port, _obj, forward_id)
@@ -1101,6 +1115,10 @@ class FirewallPolicy(object):
self._forward_port(False, _policy, transaction, port, protocol,
toport, toaddr)
+ self.removeTimeout(
+ ("forward_port", _policy, port, protocol, toport, toaddr)
+ )
+
transaction.add_post(self.__unregister_forward_port, _obj, forward_id)
if use_transaction is None:
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index 75fa486f0f92..66321939237f 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -1934,12 +1934,6 @@ class FirewallD(DbusServiceObject):
# FORWARD PORT
- @dbus_handle_exceptions
- def disable_forward_port(self, zone, port, protocol, toport, toaddr): # pylint: disable=R0913
- del self._timeouts[zone][(port, protocol, toport, toaddr)]
- self.fw.zone.remove_forward_port(zone, port, protocol, toport, toaddr)
- self.ForwardPortRemoved(zone, port, protocol, toport, toaddr)
-
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG)
@dbus_service_method(config.dbus.DBUS_INTERFACE_ZONE, in_signature='sssssi',
out_signature='s')
@@ -1960,11 +1954,9 @@ class FirewallD(DbusServiceObject):
toaddr, timeout, sender)
if timeout > 0:
- tag = GLib.timeout_add_seconds(timeout,
- self.disable_forward_port,
- _zone, port, protocol, toport,
- toaddr)
- self.addTimeout(_zone, (port, protocol, toport, toaddr), tag)
+ GLib.timeout_add_seconds(
+ timeout, self.ForwardPortRemoved, _zone, port, protocol, toport, toaddr
+ )
self.ForwardPortAdded(_zone, port, protocol, toport, toaddr, timeout)
return _zone
@@ -1987,7 +1979,6 @@ class FirewallD(DbusServiceObject):
_zone = self.fw.zone.remove_forward_port(zone, port, protocol, toport,
toaddr)
- self.removeTimeout(_zone, (port, protocol, toport, toaddr))
self.ForwardPortRemoved(_zone, port, protocol, toport, toaddr)
return _zone
--
2.52.0

View File

@ -0,0 +1,78 @@
From 45175cdb284572a7a888ee285aa8a645e41dd448 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 14:27:17 -0500
Subject: [PATCH 56/70] v2.5.0: chore(zone): icmp_block: move timeouts to
policy
(cherry picked from commit 426ba555b74958a3e43a62c2f0da4013b408fb05)
---
src/firewall/core/fw_policy.py | 8 ++++++++
src/firewall/server/firewalld.py | 12 +-----------
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index 70ca2ecf20d3..5382c9c51ef5 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -1168,6 +1168,12 @@ class FirewallPolicy(object):
if _obj.applied:
self._icmp_block(True, _policy, icmp, transaction)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(
+ timeout, self.remove_icmp_block, _policy, icmp
+ )
+ self.addTimeout(tag, ("icmp_block", _policy, icmp))
+
self.__register_icmp_block(_obj, icmp_id, timeout, sender)
transaction.add_fail(self.__unregister_icmp_block, _obj, icmp_id)
@@ -1198,6 +1204,8 @@ class FirewallPolicy(object):
if _obj.applied:
self._icmp_block(False, _policy, icmp, transaction)
+ self.removeTimeout(("icmp_block", _policy, icmp))
+
transaction.add_post(self.__unregister_icmp_block, _obj, icmp_id)
if use_transaction is None:
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index 66321939237f..913c9a8e173a 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -2028,13 +2028,6 @@ class FirewallD(DbusServiceObject):
# ICMP BLOCK
- @dbus_handle_exceptions
- def disableTimedIcmpBlock(self, zone, icmp, sender): # pylint: disable=W0613
- log.debug1("zone.disableTimedIcmpBlock('%s', '%s')" % (zone, icmp))
- del self._timeouts[zone][icmp]
- self.fw.zone.remove_icmp_block(zone, icmp)
- self.IcmpBlockRemoved(zone, icmp)
-
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG)
@dbus_service_method(config.dbus.DBUS_INTERFACE_ZONE, in_signature='ssi',
out_signature='s')
@@ -2049,9 +2042,7 @@ class FirewallD(DbusServiceObject):
_zone = self.fw.zone.add_icmp_block(zone, icmp, timeout, sender)
if timeout > 0:
- tag = GLib.timeout_add_seconds(timeout, self.disableTimedIcmpBlock,
- _zone, icmp, sender)
- self.addTimeout(_zone, icmp, tag)
+ GLib.timeout_add_seconds(timeout, self.IcmpBlockRemoved, _zone, icmp)
self.IcmpBlockAdded(_zone, icmp, timeout)
return _zone
@@ -2068,7 +2059,6 @@ class FirewallD(DbusServiceObject):
self.accessCheck(sender)
_zone = self.fw.zone.remove_icmp_block(zone, icmp)
- self.removeTimeout(_zone, icmp)
self.IcmpBlockRemoved(_zone, icmp)
return _zone
--
2.52.0

View File

@ -0,0 +1,75 @@
From b6cbb249a6342749c52c24978ff1fb6411bef729 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 14:35:02 -0500
Subject: [PATCH 57/70] v2.5.0: chore(zone): masquerade: move timeouts to
policy
(cherry picked from commit ef995448e43cdd307b6ff74f081e7db100add6c7)
---
src/firewall/core/fw_policy.py | 6 ++++++
src/firewall/server/firewalld.py | 11 +----------
2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index 5382c9c51ef5..ebb052e9caa2 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -979,6 +979,10 @@ class FirewallPolicy(object):
if _obj.applied:
self._masquerade(True, _policy, transaction)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(timeout, self.remove_masquerade, _policy)
+ self.addTimeout(tag, ("masquerade", _policy))
+
self.__register_masquerade(_obj, timeout, sender)
transaction.add_fail(self.__unregister_masquerade, _obj)
@@ -1008,6 +1012,8 @@ class FirewallPolicy(object):
if _obj.applied:
self._masquerade(False, _policy, transaction)
+ self.removeTimeout(("masquerade", _policy))
+
transaction.add_post(self.__unregister_masquerade, _obj)
if use_transaction is None:
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index 913c9a8e173a..b7ced6143734 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -1869,12 +1869,6 @@ class FirewallD(DbusServiceObject):
# MASQUERADE
- @dbus_handle_exceptions
- def disableTimedMasquerade(self, zone):
- del self._timeouts[zone]["masquerade"]
- self.fw.zone.remove_masquerade(zone)
- self.MasqueradeRemoved(zone)
-
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG)
@dbus_service_method(config.dbus.DBUS_INTERFACE_ZONE, in_signature='si',
out_signature='s')
@@ -1888,9 +1882,7 @@ class FirewallD(DbusServiceObject):
_zone = self.fw.zone.add_masquerade(zone, timeout, sender)
if timeout > 0:
- tag = GLib.timeout_add_seconds(timeout, self.disableTimedMasquerade,
- _zone)
- self.addTimeout(_zone, "masquerade", tag)
+ GLib.timeout_add_seconds(timeout, self.MasqueradeRemoved, _zone)
self.MasqueradeAdded(_zone, timeout)
return _zone
@@ -1906,7 +1898,6 @@ class FirewallD(DbusServiceObject):
self.accessCheck(sender)
_zone = self.fw.zone.remove_masquerade(zone)
- self.removeTimeout(_zone, "masquerade")
self.MasqueradeRemoved(_zone)
return _zone
--
2.52.0

View File

@ -0,0 +1,77 @@
From 331c2e576dac97695fe51d9dce3b24093adfdfb5 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 14:59:53 -0500
Subject: [PATCH 58/70] v2.5.0: chore(zone): protocol: move timeouts to policy
(cherry picked from commit 7ff66d7690f629947c96863b3980efc22b439406)
---
src/firewall/core/fw_policy.py | 8 ++++++++
src/firewall/server/firewalld.py | 12 +-----------
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index ebb052e9caa2..b477f62f640c 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -796,6 +796,12 @@ class FirewallPolicy(object):
if _obj.applied:
self._protocol(True, _policy, protocol, transaction)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(
+ timeout, self.remove_protocol, _policy, protocol
+ )
+ self.addTimeout(tag, ("protocol", _policy, protocol))
+
self.__register_protocol(_obj, protocol_id, timeout, sender)
transaction.add_fail(self.__unregister_protocol, _obj, protocol_id)
@@ -827,6 +833,8 @@ class FirewallPolicy(object):
if _obj.applied:
self._protocol(False, _policy, protocol, transaction)
+ self.removeTimeout(("protocol", _policy, protocol))
+
transaction.add_post(self.__unregister_protocol, _obj,
protocol_id)
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index b7ced6143734..ab3078b2e8b9 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -1705,13 +1705,6 @@ class FirewallD(DbusServiceObject):
# PROTOCOLS
- @dbus_handle_exceptions
- def disableTimedProtocol(self, zone, protocol):
- log.debug1("zone.disableTimedProtocol('%s', '%s')" % (zone, protocol))
- del self._timeouts[zone][(protocol)]
- self.fw.zone.remove_protocol(zone, protocol)
- self.ProtocolRemoved(zone, protocol)
-
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG)
@dbus_service_method(config.dbus.DBUS_INTERFACE_ZONE, in_signature='ssi',
out_signature='s')
@@ -1726,9 +1719,7 @@ class FirewallD(DbusServiceObject):
_zone = self.fw.zone.add_protocol(zone, protocol, timeout, sender)
if timeout > 0:
- tag = GLib.timeout_add_seconds(timeout, self.disableTimedProtocol,
- _zone, protocol)
- self.addTimeout(_zone, protocol, tag)
+ GLib.timeout_add_seconds(timeout, self.ProtocolRemoved, _zone, protocol)
self.ProtocolAdded(_zone, protocol, timeout)
return _zone
@@ -1745,7 +1736,6 @@ class FirewallD(DbusServiceObject):
self.accessCheck(sender)
_zone= self.fw.zone.remove_protocol(zone, protocol)
- self.removeTimeout(_zone, protocol)
self.ProtocolRemoved(_zone, protocol)
return _zone
--
2.52.0

View File

@ -0,0 +1,76 @@
From 0037599863132394bddfe2e609e4c8c3786627a1 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 16:29:05 -0500
Subject: [PATCH 59/70] v2.5.0: chore(zone): rule: move timeouts to policy
(cherry picked from commit cd928486a31b8fbe98a25f1a682cac2c5f9226d3)
---
src/firewall/core/fw_policy.py | 6 ++++++
src/firewall/server/firewalld.py | 13 +------------
2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index b477f62f640c..6203824166c3 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -478,6 +478,10 @@ class FirewallPolicy(object):
if _obj.applied:
self.__rule(True, _policy, rule, transaction)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(timeout, self.remove_rule, _policy, rule)
+ self.addTimeout(tag, ("rule", _policy, rule))
+
self.__register_rule(_obj, rule_id, timeout, sender)
transaction.add_fail(self.__unregister_rule, _obj, rule_id)
@@ -509,6 +513,8 @@ class FirewallPolicy(object):
if _obj.applied:
self.__rule(False, _policy, rule, transaction)
+ self.removeTimeout(("rule", _policy, rule))
+
transaction.add_post(self.__unregister_rule, _obj, rule_id)
if use_transaction is None:
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index ab3078b2e8b9..48429bc8061a 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -1474,14 +1474,6 @@ class FirewallD(DbusServiceObject):
# RICH RULES
- @dbus_handle_exceptions
- def disableTimedRichRule(self, zone, rule):
- log.debug1("zone.disableTimedRichRule('%s', '%s')" % (zone, rule))
- del self._timeouts[zone][rule]
- obj = Rich_Rule(rule_str=rule)
- self.fw.zone.remove_rule(zone, obj)
- self.RichRuleRemoved(zone, rule)
-
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG)
@dbus_service_method(config.dbus.DBUS_INTERFACE_ZONE, in_signature='ssi',
out_signature='s')
@@ -1495,9 +1487,7 @@ class FirewallD(DbusServiceObject):
_zone = self.fw.zone.add_rule(zone, obj, timeout)
if timeout > 0:
- tag = GLib.timeout_add_seconds(timeout, self.disableTimedRichRule,
- _zone, rule)
- self.addTimeout(_zone, rule, tag)
+ GLib.timeout_add_seconds(timeout, self.RichRuleRemoved, _zone, rule)
self.RichRuleAdded(_zone, rule, timeout)
return _zone
@@ -1512,7 +1502,6 @@ class FirewallD(DbusServiceObject):
log.debug1("zone.removeRichRule('%s', '%s')" % (zone, rule))
obj = Rich_Rule(rule_str=rule)
_zone = self.fw.zone.remove_rule(zone, obj)
- self.removeTimeout(_zone, rule)
self.RichRuleRemoved(_zone, rule)
return _zone
--
2.52.0

View File

@ -0,0 +1,49 @@
From 475eb2107544a4c8ef113db4a81bf1363247180c Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 16:29:50 -0500
Subject: [PATCH 60/70] v2.5.0: chore(zone): remove daemon level timeout code
As its no longer used.
(cherry picked from commit 537af3fcb09bec296869d9ee23c4d4b9b2b72141)
---
src/firewall/server/firewalld.py | 23 -----------------------
1 file changed, 23 deletions(-)
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index 48429bc8061a..cb786b63f93f 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -127,29 +127,6 @@ class FirewallD(DbusServiceObject):
return
raise FirewallError(errors.ACCESS_DENIED, "lockdown is enabled")
- # timeout functions
-
- @dbus_handle_exceptions
- def addTimeout(self, zone, x, tag):
- if zone not in self._timeouts:
- self._timeouts[zone] = { }
- self._timeouts[zone][x] = tag
-
- @dbus_handle_exceptions
- def removeTimeout(self, zone, x):
- if zone in self._timeouts and x in self._timeouts[zone]:
- GLib.source_remove(self._timeouts[zone][x])
- del self._timeouts[zone][x]
-
- @dbus_handle_exceptions
- def cleanup_timeouts(self):
- # cleanup timeouts
- for zone in self._timeouts:
- for x in self._timeouts[zone]:
- GLib.source_remove(self._timeouts[zone][x])
- self._timeouts[zone].clear()
- self._timeouts.clear()
-
# property handling
@dbus_handle_exceptions
--
2.52.0

View File

@ -0,0 +1,51 @@
From dde93f3310f79a1f739c8e7400831bf4e1b78df6 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 16:34:17 -0500
Subject: [PATCH 61/70] v2.5.0: chore(fw_zone): add utility functions to
support timeouts
(cherry picked from commit 9f3c28e065543935a6f3c7c62e336ec0a866b1c6)
---
src/firewall/core/fw_zone.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/firewall/core/fw_zone.py b/src/firewall/core/fw_zone.py
index 6c659047b97d..f55be13f8fd3 100644
--- a/src/firewall/core/fw_zone.py
+++ b/src/firewall/core/fw_zone.py
@@ -49,6 +49,7 @@ class FirewallZone(object):
self._fw = fw
self._zones = { }
self._zone_policies = { }
+ self._timeouts = {}
def __repr__(self):
return '%s(%r)' % (self.__class__, self._zones)
@@ -56,6 +57,8 @@ class FirewallZone(object):
def cleanup(self):
self._zones.clear()
self._zone_policies.clear()
+ for _id in self._timeouts:
+ self.removeTimeout(_id)
def new_transaction(self):
t = FirewallTransaction(self._fw)
@@ -400,6 +403,15 @@ class FirewallZone(object):
else:
setting_to_fn[key][0](zone, timeout=0, sender=sender)
+ def addTimeout(self, tag, _id):
+ if _id not in self._timeouts:
+ self._timeouts[_id] = tag
+
+ def removeTimeout(self, _id):
+ if _id in self._timeouts:
+ GLib.source_remove(self._timeouts[_id])
+ del self._timeouts[_id]
+
# INTERFACES
def check_interface(self, interface):
--
2.52.0

View File

@ -0,0 +1,78 @@
From b26be86bdad0c269254f3008421480edd186cde4 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 14:39:47 -0500
Subject: [PATCH 62/70] v2.5.0: chore(fw_zone): support timeouts via dict API
(cherry picked from commit 24476b6820f36cc31ba0b7fc36e63acb07ba66a5)
---
src/firewall/core/fw_zone.py | 14 +++++++++++---
src/firewall/server/firewalld.py | 9 +++++++++
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/src/firewall/core/fw_zone.py b/src/firewall/core/fw_zone.py
index f55be13f8fd3..de01aeb30a59 100644
--- a/src/firewall/core/fw_zone.py
+++ b/src/firewall/core/fw_zone.py
@@ -365,6 +365,12 @@ class FirewallZone(object):
"forward": (self.add_forward, self.remove_forward),
}
+ timeout = 0
+ if "timeout" in settings:
+ timeout = settings["timeout"]
+ settings = copy.copy(settings)
+ del settings["timeout"]
+
# do a full config check on a temporary object before trying to make
# the runtime changes
old_obj = self.get_zone(zone)
@@ -393,15 +399,17 @@ class FirewallZone(object):
setting_to_fn[key][0](zone, args, sender=sender)
else:
if isinstance(args, tuple):
- setting_to_fn[key][0](zone, *args, timeout=0, sender=sender)
+ setting_to_fn[key][0](
+ zone, *args, timeout=timeout, sender=sender
+ )
else:
- setting_to_fn[key][0](zone, args, timeout=0, sender=sender)
+ setting_to_fn[key][0](zone, args, timeout=timeout, sender=sender)
else: # bool
if key in ["icmp_block_inversion"]:
# no timeout arg
setting_to_fn[key][0](zone, sender=sender)
else:
- setting_to_fn[key][0](zone, timeout=0, sender=sender)
+ setting_to_fn[key][0](zone, timeout=timeout, sender=sender)
def addTimeout(self, tag, _id):
if _id not in self._timeouts:
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index cb786b63f93f..d796c1d45e9c 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -939,12 +939,21 @@ class FirewallD(DbusServiceObject):
self.accessCheck(sender)
self.fw.zone.set_config_with_settings_dict(zone, dbus_to_python(settings), sender)
self.ZoneUpdated(zone, settings)
+ if "timeout" in settings and settings["timeout"] > 0:
+ GLib.timeout_add_seconds(
+ settings["timeout"],
+ self.ZoneUpdatedCurrentSettings,
+ zone,
+ )
@dbus.service.signal(config.dbus.DBUS_INTERFACE_ZONE, signature='sa{sv}')
@dbus_handle_exceptions
def ZoneUpdated(self, zone, settings):
log.debug1("zone.ZoneUpdated('%s', '%s')" % (zone, settings))
+ def ZoneUpdatedCurrentSettings(self, zone):
+ self.ZoneUpdated(zone, self.fw.zone.get_config_with_settings_dict(zone))
+
@dbus_polkit_require_auth(config.dbus.PK_ACTION_CONFIG_INFO)
@dbus_service_method(config.dbus.DBUS_INTERFACE_POLICY, in_signature='s',
out_signature="a{sv}")
--
2.52.0

View File

@ -0,0 +1,76 @@
From 567de9771d0a916d2c2a6895d5bce4e764eefe66 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Thu, 20 Nov 2025 15:49:04 -0500
Subject: [PATCH 63/70] v2.5.0: fix(zone): forward: support timeout
(cherry picked from commit f1c9f6ad8c22d47906ef57ac67a7af773b783bb8)
---
src/firewall-cmd.in | 2 +-
src/firewall/client.py | 4 ++--
src/firewall/core/fw_zone.py | 8 ++++++++
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/firewall-cmd.in b/src/firewall-cmd.in
index 755e25e1c1ae..eb0ac7e48e3c 100755
--- a/src/firewall-cmd.in
+++ b/src/firewall-cmd.in
@@ -3086,7 +3086,7 @@ elif a.query_source_port:
# forward
elif a.add_forward:
- fw.addForward(zone)
+ fw.addForward(zone, a.timeout)
elif a.remove_forward:
fw.removeForward(zone)
elif a.query_forward:
diff --git a/src/firewall/client.py b/src/firewall/client.py
index c710df1b6edf..268a4a947da9 100644
--- a/src/firewall/client.py
+++ b/src/firewall/client.py
@@ -3432,8 +3432,8 @@ class FirewallClient(object):
# forward
@handle_exceptions
- def addForward(self, zone):
- self.fw_zone.setZoneSettings2(zone, {"forward": True})
+ def addForward(self, zone, timeout=0):
+ self.fw_zone.setZoneSettings2(zone, {"forward": True, "timeout": timeout})
@handle_exceptions
def queryForward(self, zone):
diff --git a/src/firewall/core/fw_zone.py b/src/firewall/core/fw_zone.py
index de01aeb30a59..302b87267c1d 100644
--- a/src/firewall/core/fw_zone.py
+++ b/src/firewall/core/fw_zone.py
@@ -19,6 +19,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+from gi.repository import GLib
+
import copy
from firewall.core.base import SHORTCUTS, DEFAULT_ZONE_TARGET, SOURCE_IPSET_TYPES
from firewall.core.fw_transaction import FirewallTransaction
@@ -1043,6 +1045,10 @@ class FirewallZone(object):
if _obj.applied:
self._forward(True, _zone, transaction)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(timeout, self.remove_forward, _zone)
+ self.addTimeout(tag, ("forward", _zone))
+
self.__register_forward(_obj, timeout, sender)
transaction.add_fail(self.__unregister_forward, _obj)
@@ -1071,6 +1077,8 @@ class FirewallZone(object):
if _obj.applied:
self._forward(False, _zone, transaction)
+ self.removeTimeout(("forward", _zone))
+
transaction.add_post(self.__unregister_forward, _obj)
if use_transaction is None:
--
2.52.0

View File

@ -0,0 +1,418 @@
From 7d010783dbecf7d5286d777d9197e253dc07fef7 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Thu, 20 Nov 2025 15:25:02 -0500
Subject: [PATCH 64/70] v2.5.0: test(zone): forward: move test to features
(cherry picked from commit db12155f6e9446b8e05d237d9f1e6998eae89f67)
---
src/tests/cli/firewall-cmd.at | 188 -----------------------------
src/tests/features/features.at | 1 +
src/tests/features/zone_forward.at | 188 +++++++++++++++++++++++++++++
3 files changed, 189 insertions(+), 188 deletions(-)
create mode 100644 src/tests/features/zone_forward.at
diff --git a/src/tests/cli/firewall-cmd.at b/src/tests/cli/firewall-cmd.at
index 4f45774bbc4a..5638e3ec65ca 100644
--- a/src/tests/cli/firewall-cmd.at
+++ b/src/tests/cli/firewall-cmd.at
@@ -505,194 +505,6 @@ FWD_START_TEST([masquerade])
FWD_CHECK([--permanent --query-masquerade], 1, ignore)
FWD_END_TEST
-FWD_START_TEST([forward])
- AT_KEYWORDS(forward gh586 gh613)
-
- FWD_CHECK([--zone=home --add-interface=dummy --add-interface=dummy2], 0, ignore)
- FWD_CHECK([--zone=home --add-forward], 0, ignore)
- NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_home_allow {
- oifname "dummy" accept
- oifname "dummy2" accept
- }
- }
- ])
- dnl These two ipXtables rules correspond to:
- dnl -A FWD_home_allow -o dummy -j ACCEPT
- dnl -A FWD_home_allow -o dummy2 -j ACCEPT
- dnl although we can't assert the interface names because they don't
- dnl appear in these rule listings, unfortunately...
- IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
- ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ACCEPT 0 -- ::/0 ::/0
- ACCEPT 0 -- ::/0 ::/0
- ])
- dnl Forward rules should be updated when the interfaces change
- FWD_CHECK([--zone=home --remove-interface=dummy2], 0, ignore)
- NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_home_allow {
- oifname "dummy" accept
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ACCEPT 0 -- ::/0 ::/0
- ])
- FWD_CHECK([--zone=home --add-interface=dummy3], 0, ignore)
- NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_home_allow {
- oifname "dummy" accept
- oifname "dummy3" accept
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
- ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ACCEPT 0 -- ::/0 ::/0
- ACCEPT 0 -- ::/0 ::/0
- ])
- FWD_CHECK([--zone=home --query-forward], 0, ignore)
- FWD_CHECK([--zone=home --remove-forward], 0, ignore)
- NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_home_allow {
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ])
- FWD_CHECK([--zone=home --query-forward], 1, ignore)
- FWD_CHECK([--zone=home --remove-interface=dummy --remove-interface=dummy3], 0, ignore)
-
- FWD_CHECK([--permanent --zone=home --add-forward], 0, ignore)
- FWD_CHECK([-q --permanent --zone=home --add-interface=dummy --add-interface=dummy3])
- FWD_CHECK([-q --permanent --zone=home --add-source=10.10.10.0/24])
- FWD_RELOAD
- FWD_CHECK([--permanent --zone=home --query-forward], 0, ignore)
- NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_home_allow {
- oifname "dummy" accept
- oifname "dummy3" accept
- ip daddr 10.10.10.0/24 accept
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
- ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
- ACCEPT 0 -- 0.0.0.0/0 10.10.10.0/24
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
- ACCEPT 0 -- ::/0 ::/0
- ACCEPT 0 -- ::/0 ::/0
- ])
- FWD_CHECK([--permanent --zone=home --remove-forward], 0, ignore)
- FWD_CHECK([--permanent --zone=home --query-forward], 1, ignore)
- FWD_CHECK([-q --permanent --zone=home --remove-interface=dummy --remove-interface=dummy3])
- FWD_CHECK([-q --permanent --zone=home --remove-source=10.10.10.0/24])
- FWD_RELOAD
-
- dnl verify enabled in default zone doesn't add a wildcard/catch-all entry
- FWD_CHECK([--get-default-zone |grep public], 0, [ignore])
- FWD_CHECK([-q --add-interface dummy4])
- FWD_CHECK([-q --add-forward])
- NFT_LIST_RULES([inet], [filter_FWD_public_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_public_allow {
- oifname "dummy4" accept
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_public_allow], 0, [dnl
- ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_public_allow], 0, [dnl
- ACCEPT 0 -- ::/0 ::/0
- ])
-
- dnl zone source
- FWD_CHECK([--zone=internal --add-source=10.10.10.0/24], 0, ignore)
- IF_HOST_SUPPORTS_IPV6_RULES([
- FWD_CHECK([--zone=internal --add-source=1234::/64], 0, ignore)
- ])
- FWD_CHECK([--zone=internal --add-forward], 0, ignore)
- NFT_LIST_RULES([inet], [filter_FWD_internal_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_internal_allow {
- ip daddr 10.10.10.0/24 accept
- ip6 daddr 1234::/64 accept
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
- ACCEPT 0 -- 0.0.0.0/0 10.10.10.0/24
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
- ACCEPT 0 -- ::/0 1234::/64
- ])
- IF_HOST_SUPPORTS_IPV6_RULES([
- FWD_CHECK([--zone=internal --remove-source=1234::/64], 0, ignore)
- ])
- NFT_LIST_RULES([inet], [filter_FWD_internal_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_internal_allow {
- ip daddr 10.10.10.0/24 accept
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
- ACCEPT 0 -- 0.0.0.0/0 10.10.10.0/24
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
- ])
- FWD_CHECK([--zone=internal --add-source=10.20.20.0/24], 0, ignore)
- IF_HOST_SUPPORTS_IPV6_RULES([
- FWD_CHECK([--zone=internal --add-source=4321::/64], 0, ignore)
- ])
- NFT_LIST_RULES([inet], [filter_FWD_internal_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_internal_allow {
- ip daddr 10.10.10.0/24 accept
- ip daddr 10.20.20.0/24 accept
- ip6 daddr 4321::/64 accept
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
- ACCEPT 0 -- 0.0.0.0/0 10.10.10.0/24
- ACCEPT 0 -- 0.0.0.0/0 10.20.20.0/24
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
- ACCEPT 0 -- ::/0 4321::/64
- ])
- FWD_CHECK([--zone=internal --remove-forward], 0, ignore)
- NFT_LIST_RULES([inet], [filter_FWD_internal_allow], 0, [dnl
- table inet firewalld {
- chain filter_FWD_internal_allow {
- }
- }
- ])
- IPTABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
- ])
- IP6TABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
- ])
-FWD_END_TEST
-
FWD_START_TEST([forward ports])
AT_KEYWORDS(port forward_port)
diff --git a/src/tests/features/features.at b/src/tests/features/features.at
index 83ad9d122189..8f7c6bcafec7 100644
--- a/src/tests/features/features.at
+++ b/src/tests/features/features.at
@@ -22,3 +22,4 @@ m4_include([features/reset_defaults.at])
m4_include([features/iptables_no_flush_on_shutdown.at])
m4_include([features/reloadpolicy.at])
m4_include([features/nftables_table_owner.at])
+m4_include([features/zone_forward.at])
diff --git a/src/tests/features/zone_forward.at b/src/tests/features/zone_forward.at
new file mode 100644
index 000000000000..79129cee5192
--- /dev/null
+++ b/src/tests/features/zone_forward.at
@@ -0,0 +1,188 @@
+FWD_START_TEST([zone - forward])
+AT_KEYWORDS(forward gh586 gh613)
+
+FWD_CHECK([--zone=home --add-interface=dummy --add-interface=dummy2], 0, ignore)
+FWD_CHECK([--zone=home --add-forward], 0, ignore)
+NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_home_allow {
+ oifname "dummy" accept
+ oifname "dummy2" accept
+ }
+ }
+])
+dnl These two ipXtables rules correspond to:
+dnl -A FWD_home_allow -o dummy -j ACCEPT
+dnl -A FWD_home_allow -o dummy2 -j ACCEPT
+dnl although we can't assert the interface names because they don't
+dnl appear in these rule listings, unfortunately...
+IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+])
+IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+ ACCEPT 0 -- ::/0 ::/0
+ ACCEPT 0 -- ::/0 ::/0
+])
+dnl Forward rules should be updated when the interfaces change
+FWD_CHECK([--zone=home --remove-interface=dummy2], 0, ignore)
+NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_home_allow {
+ oifname "dummy" accept
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+])
+IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+ ACCEPT 0 -- ::/0 ::/0
+])
+FWD_CHECK([--zone=home --add-interface=dummy3], 0, ignore)
+NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_home_allow {
+ oifname "dummy" accept
+ oifname "dummy3" accept
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+])
+IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+ ACCEPT 0 -- ::/0 ::/0
+ ACCEPT 0 -- ::/0 ::/0
+])
+FWD_CHECK([--zone=home --query-forward], 0, ignore)
+FWD_CHECK([--zone=home --remove-forward], 0, ignore)
+NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_home_allow {
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+])
+IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+])
+FWD_CHECK([--zone=home --query-forward], 1, ignore)
+FWD_CHECK([--zone=home --remove-interface=dummy --remove-interface=dummy3], 0, ignore)
+
+FWD_CHECK([--permanent --zone=home --add-forward], 0, ignore)
+FWD_CHECK([-q --permanent --zone=home --add-interface=dummy --add-interface=dummy3])
+FWD_CHECK([-q --permanent --zone=home --add-source=10.10.10.0/24])
+FWD_RELOAD
+FWD_CHECK([--permanent --zone=home --query-forward], 0, ignore)
+NFT_LIST_RULES([inet], [filter_FWD_home_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_home_allow {
+ oifname "dummy" accept
+ oifname "dummy3" accept
+ ip daddr 10.10.10.0/24 accept
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+ ACCEPT 0 -- 0.0.0.0/0 10.10.10.0/24
+])
+IP6TABLES_LIST_RULES([filter], [FWD_home_allow], 0, [dnl
+ ACCEPT 0 -- ::/0 ::/0
+ ACCEPT 0 -- ::/0 ::/0
+])
+FWD_CHECK([--permanent --zone=home --remove-forward], 0, ignore)
+FWD_CHECK([--permanent --zone=home --query-forward], 1, ignore)
+FWD_CHECK([-q --permanent --zone=home --remove-interface=dummy --remove-interface=dummy3])
+FWD_CHECK([-q --permanent --zone=home --remove-source=10.10.10.0/24])
+FWD_RELOAD
+
+dnl verify enabled in default zone doesn't add a wildcard/catch-all entry
+FWD_CHECK([--get-default-zone |grep public], 0, [ignore])
+FWD_CHECK([-q --add-interface dummy4])
+FWD_CHECK([-q --add-forward])
+NFT_LIST_RULES([inet], [filter_FWD_public_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_public_allow {
+ oifname "dummy4" accept
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_public_allow], 0, [dnl
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+])
+IP6TABLES_LIST_RULES([filter], [FWD_public_allow], 0, [dnl
+ ACCEPT 0 -- ::/0 ::/0
+])
+
+dnl zone source
+FWD_CHECK([--zone=internal --add-source=10.10.10.0/24], 0, ignore)
+IF_HOST_SUPPORTS_IPV6_RULES([
+FWD_CHECK([--zone=internal --add-source=1234::/64], 0, ignore)
+])
+FWD_CHECK([--zone=internal --add-forward], 0, ignore)
+NFT_LIST_RULES([inet], [filter_FWD_internal_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_internal_allow {
+ ip daddr 10.10.10.0/24 accept
+ ip6 daddr 1234::/64 accept
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
+ ACCEPT 0 -- 0.0.0.0/0 10.10.10.0/24
+])
+IP6TABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
+ ACCEPT 0 -- ::/0 1234::/64
+])
+IF_HOST_SUPPORTS_IPV6_RULES([
+FWD_CHECK([--zone=internal --remove-source=1234::/64], 0, ignore)
+])
+NFT_LIST_RULES([inet], [filter_FWD_internal_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_internal_allow {
+ ip daddr 10.10.10.0/24 accept
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
+ ACCEPT 0 -- 0.0.0.0/0 10.10.10.0/24
+])
+IP6TABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
+])
+FWD_CHECK([--zone=internal --add-source=10.20.20.0/24], 0, ignore)
+IF_HOST_SUPPORTS_IPV6_RULES([
+FWD_CHECK([--zone=internal --add-source=4321::/64], 0, ignore)
+])
+NFT_LIST_RULES([inet], [filter_FWD_internal_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_internal_allow {
+ ip daddr 10.10.10.0/24 accept
+ ip daddr 10.20.20.0/24 accept
+ ip6 daddr 4321::/64 accept
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
+ ACCEPT 0 -- 0.0.0.0/0 10.10.10.0/24
+ ACCEPT 0 -- 0.0.0.0/0 10.20.20.0/24
+])
+IP6TABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
+ ACCEPT 0 -- ::/0 4321::/64
+])
+FWD_CHECK([--zone=internal --remove-forward], 0, ignore)
+NFT_LIST_RULES([inet], [filter_FWD_internal_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_internal_allow {
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
+])
+IP6TABLES_LIST_RULES([filter], [FWD_internal_allow], 0, [dnl
+])
+
+FWD_END_TEST()
--
2.52.0

View File

@ -0,0 +1,214 @@
From 5419b3e69790b4ee2c106d01bc7fba64ba6a2c6f Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Thu, 20 Nov 2025 15:29:07 -0500
Subject: [PATCH 65/70] v2.5.0: test(zone): verify timeout works
(cherry picked from commit 6214af87870637383671c45ad954be1ebae29c8e)
---
src/tests/features/features.at | 1 +
src/tests/features/zone_timeout.at | 184 +++++++++++++++++++++++++++++
2 files changed, 185 insertions(+)
create mode 100644 src/tests/features/zone_timeout.at
diff --git a/src/tests/features/features.at b/src/tests/features/features.at
index 8f7c6bcafec7..2867132f7b08 100644
--- a/src/tests/features/features.at
+++ b/src/tests/features/features.at
@@ -23,3 +23,4 @@ m4_include([features/iptables_no_flush_on_shutdown.at])
m4_include([features/reloadpolicy.at])
m4_include([features/nftables_table_owner.at])
m4_include([features/zone_forward.at])
+m4_include([features/zone_timeout.at])
diff --git a/src/tests/features/zone_timeout.at b/src/tests/features/zone_timeout.at
new file mode 100644
index 000000000000..c0ef68c7cefb
--- /dev/null
+++ b/src/tests/features/zone_timeout.at
@@ -0,0 +1,184 @@
+m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [], [
+FWD_START_TEST([zone - timeouts])
+AT_KEYWORDS(zone timeout)
+
+FWD_CHECK([--permanent --zone trusted --add-icmp-block-inversion], 0, [ignore])
+FWD_CHECK([--permanent --zone trusted --add-interface foobar], 0, [ignore])
+FWD_CHECK([--permanent --zone trusted --remove-forward], 0, [ignore])
+FWD_RELOAD()
+
+dnl $1 = firewall-cmd args
+dnl $2 = nftables expected input chain rules
+dnl $3 = nftables expected forward chain rules
+dnl $4 = nftables expected nat prerouting chain rules
+dnl $5 = nftables expected nat postrouting chain rules
+dnl $6 = iptables expected input chain rules
+dnl $7 = iptables expected forward chain rules
+dnl $8 = iptables expected nat prerouting chain rules
+dnl $9 = iptables expected nat postrouting chain rules
+m4_define([do_timeout], [dnl
+
+FWD_CHECK([--zone trusted --timeout 2 $1], 0, [ignore])
+FWD_CHECK([--zone trusted --add-service https], 0, [ignore])
+
+NFT_LIST_RULES([inet], [filter_IN_trusted_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_IN_trusted_allow {
+ $2 dnl
+ tcp dport 443 accept
+ }
+ }
+])
+NFT_LIST_RULES([inet], [filter_FWD_trusted_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_trusted_allow {
+ $3 dnl
+ }
+ }
+])
+NFT_LIST_RULES([inet], [nat_PRE_trusted_allow], 0, [dnl
+ table inet firewalld {
+ chain nat_PRE_trusted_allow {
+ $4 dnl
+ }
+ }
+])
+NFT_LIST_RULES([inet], [nat_POST_trusted_allow], 0, [dnl
+ table inet firewalld {
+ chain nat_POST_trusted_allow {
+ $5 dnl
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [IN_trusted_allow], 0, [dnl
+ $6 dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
+])
+IPTABLES_LIST_RULES([filter], [FWD_trusted_allow], 0, [dnl
+ $7 dnl
+])
+IPTABLES_LIST_RULES([nat], [PRE_trusted_allow], 0, [dnl
+ $8 dnl
+])
+IPTABLES_LIST_RULES([nat], [POST_trusted_allow], 0, [dnl
+ $9 dnl
+])
+
+sleep 5
+NFT_LIST_RULES([inet], [filter_IN_trusted_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_IN_trusted_allow {
+ tcp dport 443 accept
+ }
+ }
+])
+NFT_LIST_RULES([inet], [filter_FWD_trusted_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_trusted_allow {
+ }
+ }
+])
+NFT_LIST_RULES([inet], [nat_PRE_trusted_allow], 0, [dnl
+ table inet firewalld {
+ chain nat_PRE_trusted_allow {
+ }
+ }
+])
+NFT_LIST_RULES([inet], [nat_POST_trusted_allow], 0, [dnl
+ table inet firewalld {
+ chain nat_POST_trusted_allow {
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [IN_trusted_allow], 0, [dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
+])
+IPTABLES_LIST_RULES([filter], [FWD_trusted_allow], 0, [dnl
+])
+IPTABLES_LIST_RULES([nat], [PRE_trusted_allow], 0, [dnl
+])
+IPTABLES_LIST_RULES([nat], [POST_trusted_allow], 0, [dnl
+])
+
+FWD_CHECK([--zone trusted --remove-service https], 0, [ignore])
+
+]) dnl end m4_define()
+
+dnl ##################################
+dnl ##### Test every option that #####
+dnl ##### supports timeouts #####
+dnl ##################################
+
+do_timeout([--add-port 1234/tcp],
+ tcp dport 1234 accept
+[dnl
+], [], [], [],
+[dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:1234
+], [], [], [])
+
+do_timeout([--add-source-port 1234/tcp],
+[dnl
+ tcp sport 1234 accept
+], [], [], [],
+[dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp spt:1234
+], [], [], [])
+
+do_timeout([--add-protocol igmp],
+ meta l4proto igmp accept
+[dnl
+], [], [], [],
+[dnl
+ ACCEPT 2 -- 0.0.0.0/0 0.0.0.0/0
+], [], [], [])
+
+do_timeout([--add-service http],
+ tcp dport 80 accept
+[dnl
+], [], [], [],
+[dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
+], [], [], [])
+
+do_timeout([--add-rich-rule 'rule service name=irc accept'],
+[dnl
+ tcp dport 6667 accept
+], [], [], [],
+[dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6667
+], [], [], [])
+
+do_timeout([--add-icmp-block echo-request],
+[dnl
+ icmp echo-request accept
+ icmpv6 echo-request accept
+], [], [], [],
+[dnl
+ ACCEPT 1 -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
+], [], [], [])
+
+do_timeout([--add-forward],
+[], [dnl
+ oifname "foobar" accept
+], [], [], [], [dnl
+ ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
+], [], [])
+
+do_timeout([--add-forward-port port=2222:proto=tcp:toport=22],
+[], [], [dnl
+ meta nfproto ipv4 tcp dport 2222 redirect to :22
+], [], [], [], [dnl
+ DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:2222 to::22
+], [])
+
+do_timeout([--add-masquerade],
+[], [], [], [dnl
+ meta nfproto ipv4 oifname != "lo" masquerade
+], [], [], [], [dnl
+ MASQUERADE 0 -- 0.0.0.0/0 0.0.0.0/0
+])
+
+m4_undefine([do_timeout])
+FWD_END_TEST()
+])
--
2.52.0

View File

@ -0,0 +1,74 @@
From 83d090687b36ac4c704117ec619726a8d8275e86 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Mon, 1 Dec 2025 14:53:28 -0500
Subject: [PATCH 66/70] v2.5.0: chore(fw_policy): support timeouts
(cherry picked from commit 0749229070a3f201e435ba8101be420fa0e025ad)
---
src/firewall/core/fw_policy.py | 14 +++++++++++---
src/firewall/server/firewalld.py | 9 +++++++++
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index 6203824166c3..624f8420dc5c 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -192,6 +192,12 @@ class FirewallPolicy(object):
"egress_zones": (self.add_egress_zone, self.remove_egress_zone),
}
+ timeout = 0
+ if "timeout" in settings:
+ timeout = settings["timeout"]
+ settings = copy.copy(settings)
+ del settings["timeout"]
+
# do a full config check on a temporary object before trying to make
# the runtime changes
old_obj = self.get_policy(policy)
@@ -216,11 +222,13 @@ class FirewallPolicy(object):
if isinstance(add_settings[key], list):
for args in add_settings[key]:
if isinstance(args, tuple):
- setting_to_fn[key][0](policy, *args, timeout=0, sender=sender)
+ setting_to_fn[key][0](
+ policy, *args, timeout=timeout, sender=sender
+ )
else:
- setting_to_fn[key][0](policy, args, timeout=0, sender=sender)
+ setting_to_fn[key][0](policy, args, timeout=timeout, sender=sender)
else: # bool
- setting_to_fn[key][0](policy, timeout=0, sender=sender)
+ setting_to_fn[key][0](policy, timeout=timeout, sender=sender)
def addTimeout(self, tag, _id):
if _id not in self._timeouts:
diff --git a/src/firewall/server/firewalld.py b/src/firewall/server/firewalld.py
index d796c1d45e9c..ec0c3ff4b457 100644
--- a/src/firewall/server/firewalld.py
+++ b/src/firewall/server/firewalld.py
@@ -972,12 +972,21 @@ class FirewallD(DbusServiceObject):
self.accessCheck(sender)
self.fw.policy.set_config_with_settings_dict(policy, dbus_to_python(settings), sender)
self.PolicyUpdated(policy, settings)
+ if "timeout" in settings and settings["timeout"] > 0:
+ GLib.timeout_add_seconds(
+ settings["timeout"],
+ self.PolicyUpdatedCurrentSettings,
+ policy,
+ )
@dbus.service.signal(config.dbus.DBUS_INTERFACE_POLICY, signature='sa{sv}')
@dbus_handle_exceptions
def PolicyUpdated(self, policy, settings):
log.debug1("policy.PolicyUpdated('%s', '%s')" % (policy, settings))
+ def PolicyUpdatedCurrentSettings(self, policy):
+ self.PolicyUpdated(policy, self.fw.policy.get_config_with_settings_dict(policy))
+
@dbus_polkit_require_auth(config.dbus.PK_ACTION_INFO)
@dbus_service_method(config.dbus.DBUS_INTERFACE, in_signature='',
out_signature='as')
--
2.52.0

View File

@ -0,0 +1,97 @@
From 1ffa7613a57118ff62158c0a90b3b2d168c47c25 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Wed, 3 Dec 2025 16:21:24 -0500
Subject: [PATCH 67/70] v2.5.0: fix(policy): support timeouts
Fixes: #1381
Fixes: RHEL-129918
Fixes: RHEL-95705
Fixes: RHEL-5795
(cherry picked from commit 16d8c4dd54e43b9cc66c4707b06a39cfbbd95825)
---
src/firewall-cmd.in | 2 +-
src/firewall/client.py | 6 ++++--
src/firewall/core/fw_policy.py | 16 ++++++++++++++++
3 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/src/firewall-cmd.in b/src/firewall-cmd.in
index eb0ac7e48e3c..12df581498ef 100755
--- a/src/firewall-cmd.in
+++ b/src/firewall-cmd.in
@@ -3007,7 +3007,7 @@ elif a.policy:
cmd.query_sequence(a.query_icmp_block, settings.queryIcmpBlock,
None, "'%s'")
- fw.setPolicySettings(a.policy, settings)
+ fw.setPolicySettings(a.policy, settings, a.timeout)
# endif a.policy
#
diff --git a/src/firewall/client.py b/src/firewall/client.py
index 268a4a947da9..b30b0d12f738 100644
--- a/src/firewall/client.py
+++ b/src/firewall/client.py
@@ -3293,8 +3293,10 @@ class FirewallClient(object):
return FirewallClientPolicySettings(dbus_to_python(self.fw_policy.getPolicySettings(policy)))
@handle_exceptions
- def setPolicySettings(self, policy, settings):
- self.fw_policy.setPolicySettings(policy, settings.getRuntimeSettingsDbusDict())
+ def setPolicySettings(self, policy, settings, timeout=0):
+ settings = settings.getRuntimeSettingsDbusDict()
+ settings["timeout"] = timeout
+ self.fw_policy.setPolicySettings(policy, settings)
@handle_exceptions
def getPolicies(self):
diff --git a/src/firewall/core/fw_policy.py b/src/firewall/core/fw_policy.py
index 624f8420dc5c..0a0d1ded5fe3 100644
--- a/src/firewall/core/fw_policy.py
+++ b/src/firewall/core/fw_policy.py
@@ -286,6 +286,12 @@ class FirewallPolicy(object):
self.__register_ingress_zone(_obj, zone_id, timeout, sender)
transaction.add_fail(self.__unregister_ingress_zone, _obj, zone_id)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(
+ timeout, self.remove_ingress_zone, _policy, zone
+ )
+ self.addTimeout(tag, ("ingress_zone", _policy, zone))
+
if use_transaction is None:
transaction.execute(True)
@@ -322,6 +328,8 @@ class FirewallPolicy(object):
else:
transaction.add_post(self.__unregister_ingress_zone, _obj, zone_id)
+ self.removeTimeout(("ingress_zone", _policy, zone))
+
if use_transaction is None:
transaction.execute(True)
@@ -384,6 +392,12 @@ class FirewallPolicy(object):
self.__register_egress_zone(_obj, zone_id, timeout, sender)
transaction.add_fail(self.__unregister_egress_zone, _obj, zone_id)
+ if timeout > 0:
+ tag = GLib.timeout_add_seconds(
+ timeout, self.remove_egress_zone, _policy, zone
+ )
+ self.addTimeout(tag, ("egress_zone", _policy, zone))
+
if use_transaction is None:
transaction.execute(True)
@@ -420,6 +434,8 @@ class FirewallPolicy(object):
else:
transaction.add_post(self.__unregister_egress_zone, _obj, zone_id)
+ self.removeTimeout(("egress_zone", _policy, zone))
+
if use_transaction is None:
transaction.execute(True)
--
2.52.0

View File

@ -0,0 +1,26 @@
From 4f965d0dc42c0e88b4a36014e6db9984f7402416 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Fri, 5 Dec 2025 09:51:20 -0500
Subject: [PATCH 68/70] v2.5.0: fix(cli): policy: allow timeout with
--ingress-zone/--egress-zone
(cherry picked from commit 4227d2a9b91bdf84823724b6299b984d29385ed6)
---
src/firewall-cmd.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/firewall-cmd.in b/src/firewall-cmd.in
index 12df581498ef..6973a643bf47 100755
--- a/src/firewall-cmd.in
+++ b/src/firewall-cmd.in
@@ -1104,6 +1104,7 @@ else:
if a.timeout and not (a.add_service or a.add_port or a.add_protocol or \
a.add_icmp_block or a.add_forward_port or \
a.add_source_port or a.add_forward or \
+ a.add_ingress_zone or a.add_egress_zone or \
a.add_masquerade or a.add_rich_rule):
cmd.fail(parser.format_usage() + "Wrong --timeout usage")
--
2.52.0

View File

@ -0,0 +1,237 @@
From 9acf188c98f8c654a3b04e8aba0124fa895e2784 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Thu, 20 Nov 2025 14:55:40 -0500
Subject: [PATCH 69/70] v2.5.0: test(policy): verify timeout works
Coverage: #1381
Coverage: RHEL-129918
Coverage: RHEL-95705
Coverage: RHEL-5795
(cherry picked from commit 14dde1c406841af3499db18308eb4e9e4e6f66db)
---
src/tests/features/features.at | 1 +
src/tests/features/policy_timeout.at | 203 +++++++++++++++++++++++++++
2 files changed, 204 insertions(+)
create mode 100644 src/tests/features/policy_timeout.at
diff --git a/src/tests/features/features.at b/src/tests/features/features.at
index 2867132f7b08..3501e028d589 100644
--- a/src/tests/features/features.at
+++ b/src/tests/features/features.at
@@ -24,3 +24,4 @@ m4_include([features/reloadpolicy.at])
m4_include([features/nftables_table_owner.at])
m4_include([features/zone_forward.at])
m4_include([features/zone_timeout.at])
+m4_include([features/policy_timeout.at])
diff --git a/src/tests/features/policy_timeout.at b/src/tests/features/policy_timeout.at
new file mode 100644
index 000000000000..a62493e5986f
--- /dev/null
+++ b/src/tests/features/policy_timeout.at
@@ -0,0 +1,203 @@
+m4_ifdef([TESTING_FIREWALL_OFFLINE_CMD], [], [
+FWD_START_TEST([policy - timeout])
+AT_KEYWORDS(policy timeout RHEL-129918 RHEL-95705 RHEL-5795 gh1381)
+
+FWD_CHECK([--permanent --zone trusted --add-interface foobar0], 0, [ignore])
+FWD_CHECK([--permanent --new-policy foobar], 0, [ignore])
+FWD_CHECK([--permanent --policy foobar --add-ingress-zone ANY], 0, [ignore])
+FWD_CHECK([--permanent --policy foobar --add-egress-zone ANY], 0, [ignore])
+FWD_RELOAD()
+
+dnl $1 = firewall-cmd args
+dnl $2 = nftables expected forward allow chain rules
+dnl $3 = nftables expected forward deny chain rules
+dnl $4 = nftables expected nat prerouting chain rules
+dnl $5 = nftables expected nat postrouting chain rules
+dnl $6 = iptables expected forward allow chain rules
+dnl $7 = iptables expected forward deny chain rules
+dnl $8 = iptables expected nat prerouting chain rules
+dnl $9 = iptables expected nat postrouting chain rules
+m4_define([do_timeout], [dnl
+
+FWD_CHECK([--policy foobar --timeout 2 $1], 0, [ignore])
+FWD_CHECK([--policy foobar --add-service https], 0, [ignore])
+
+NFT_LIST_RULES([inet], [filter_FWD_policy_foobar_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_policy_foobar_allow {
+ $2 dnl
+ tcp dport 443 accept
+ }
+ }
+])
+NFT_LIST_RULES([inet], [filter_FWD_policy_foobar_deny], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_policy_foobar_deny {
+ $3 dnl
+ }
+ }
+])
+NFT_LIST_RULES([inet], [nat_PRE_policy_foobar_allow], 0, [dnl
+ table inet firewalld {
+ chain nat_PRE_policy_foobar_allow {
+ $4 dnl
+ }
+ }
+])
+NFT_LIST_RULES([inet], [nat_POST_policy_foobar_allow], 0, [dnl
+ table inet firewalld {
+ chain nat_POST_policy_foobar_allow {
+ $5 dnl
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_foobar_allow], 0, [dnl
+ $6 dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
+])
+IPTABLES_LIST_RULES([filter], [FWD_foobar_deny], 0, [dnl
+ $7 dnl
+])
+IPTABLES_LIST_RULES([nat], [PRE_foobar_allow], 0, [dnl
+ $8 dnl
+])
+IPTABLES_LIST_RULES([nat], [POST_foobar_allow], 0, [dnl
+ $9 dnl
+])
+
+sleep 5
+NFT_LIST_RULES([inet], [filter_FWD_policy_foobar_allow], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_policy_foobar_allow {
+ tcp dport 443 accept
+ }
+ }
+])
+NFT_LIST_RULES([inet], [filter_FWD_policy_foobar_deny], 0, [dnl
+ table inet firewalld {
+ chain filter_FWD_policy_foobar_deny {
+ }
+ }
+])
+NFT_LIST_RULES([inet], [nat_PRE_policy_foobar_allow], 0, [dnl
+ table inet firewalld {
+ chain nat_PRE_policy_foobar_allow {
+ }
+ }
+])
+NFT_LIST_RULES([inet], [nat_POST_policy_foobar_allow], 0, [dnl
+ table inet firewalld {
+ chain nat_POST_policy_foobar_allow {
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FWD_foobar_allow], 0, [dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
+])
+IPTABLES_LIST_RULES([filter], [FWD_foobar_deny], 0, [dnl
+])
+IPTABLES_LIST_RULES([nat], [PRE_foobar_allow], 0, [dnl
+])
+IPTABLES_LIST_RULES([nat], [POST_foobar_allow], 0, [dnl
+])
+
+FWD_CHECK([--policy foobar --remove-service https], 0, [ignore])
+
+]) dnl end m4_define()
+
+dnl ##################################
+dnl ##### Test every option that #####
+dnl ##### supports timeouts #####
+dnl ##################################
+
+do_timeout([--add-port 1234/tcp],
+[dnl
+ tcp dport 1234 accept
+], [], [], [],
+[dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:1234
+], [], [], [])
+
+do_timeout([--add-source-port 1234/tcp],
+[dnl
+ tcp sport 1234 accept
+], [], [], [],
+[dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp spt:1234
+], [], [], [])
+
+do_timeout([--add-protocol igmp],
+[dnl
+ meta l4proto igmp accept
+], [], [], [],
+[dnl
+ ACCEPT 2 -- 0.0.0.0/0 0.0.0.0/0
+], [], [], [])
+
+do_timeout([--add-service http],
+[dnl
+ tcp dport 80 accept
+], [], [], [],
+[dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
+], [], [], [])
+
+do_timeout([--add-rich-rule 'rule service name=irc accept'],
+[dnl
+ tcp dport 6667 accept
+], [], [], [],
+[dnl
+ ACCEPT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6667
+], [], [], [])
+
+do_timeout([--add-icmp-block echo-request],
+[], [dnl
+ icmp echo-request reject with icmpx admin-prohibited
+ icmpv6 echo-request reject with icmpx admin-prohibited
+], [], [], [],
+[dnl
+ REJECT 1 -- 0.0.0.0/0 0.0.0.0/0 icmptype 8 reject-with icmp-host-prohibited
+], [], [])
+
+do_timeout([--add-forward-port port=2222:proto=tcp:toport=22:toaddr=10.10.10.10],
+[], [], [dnl
+ meta nfproto ipv4 tcp dport 2222 dnat ip to 10.10.10.10:22
+], [], [], [], [dnl
+ DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:2222 to:10.10.10.10:22
+], [])
+
+do_timeout([--add-masquerade],
+[], [], [], [dnl
+ meta nfproto ipv4 oifname != "lo" masquerade
+], [], [], [], [dnl
+ MASQUERADE 0 -- 0.0.0.0/0 0.0.0.0/0
+])
+
+dnl for ingress-zone and egress-zone we have to check the dispatch
+FWD_CHECK([--policy foobar --remove-ingress-zone ANY], 0, [ignore])
+FWD_CHECK([--policy foobar --timeout 2 --add-ingress-zone ANY], 0, [ignore])
+
+NFT_LIST_RULES([inet], [filter_FORWARD_POLICIES_pre], 0, [dnl
+ table inet firewalld {
+ chain filter_FORWARD_POLICIES_pre {
+ jump filter_FWD_policy_foobar
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FORWARD_POLICIES_pre], 0, [dnl
+ FWD_foobar 0 -- 0.0.0.0/0 0.0.0.0/0
+])
+
+sleep 5
+NFT_LIST_RULES([inet], [filter_FORWARD_POLICIES_pre], 0, [dnl
+ table inet firewalld {
+ chain filter_FORWARD_POLICIES_pre {
+ }
+ }
+])
+IPTABLES_LIST_RULES([filter], [FORWARD_POLICIES_pre], 0, [dnl
+])
+
+m4_undefine([do_timeout])
+FWD_END_TEST()
+])
--
2.52.0

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: 18%{?dist}
Release: 19%{?dist}
URL: http://www.firewalld.org
License: GPLv2+
Source0: https://github.com/firewalld/firewalld/releases/download/v%{version}/firewalld-%{version}.tar.bz2
@ -53,6 +53,27 @@ Patch45: 0045-v2.4.0-chore-nftables-simplify-icmp-match-fragments.patch
Patch46: 0046-v2.4.0-chore-nftables-move-_icmp_types_fragments-ins.patch
Patch47: 0047-v2.4.0-chore-ipXtables-simplify-icmp-match-fragments.patch
Patch48: 0048-v2.4.0-fix-policy-allow-host-ipv6-allow-MLD-packets.patch
Patch49: 0049-v2.3.0-fix-policy-timeout-argument-for-rich-rules.patch
Patch50: 0050-v2.5.0-test-functions-fix-macro-CHECK_NFT_CT_HELPER.patch
Patch51: 0051-v2.5.0-chore-fw_policy-add-utility-functions-to-supp.patch
Patch52: 0052-v2.5.0-chore-zone-service-move-timeouts-to-policy.patch
Patch53: 0053-v2.5.0-chore-zone-port-move-timeouts-to-policy.patch
Patch54: 0054-v2.5.0-chore-zone-source_port-move-timeouts-to-polic.patch
Patch55: 0055-v2.5.0-chore-zone-forward_port-move-timeouts-to-poli.patch
Patch56: 0056-v2.5.0-chore-zone-icmp_block-move-timeouts-to-policy.patch
Patch57: 0057-v2.5.0-chore-zone-masquerade-move-timeouts-to-policy.patch
Patch58: 0058-v2.5.0-chore-zone-protocol-move-timeouts-to-policy.patch
Patch59: 0059-v2.5.0-chore-zone-rule-move-timeouts-to-policy.patch
Patch60: 0060-v2.5.0-chore-zone-remove-daemon-level-timeout-code.patch
Patch61: 0061-v2.5.0-chore-fw_zone-add-utility-functions-to-suppor.patch
Patch62: 0062-v2.5.0-chore-fw_zone-support-timeouts-via-dict-API.patch
Patch63: 0063-v2.5.0-fix-zone-forward-support-timeout.patch
Patch64: 0064-v2.5.0-test-zone-forward-move-test-to-features.patch
Patch65: 0065-v2.5.0-test-zone-verify-timeout-works.patch
Patch66: 0066-v2.5.0-chore-fw_policy-support-timeouts.patch
Patch67: 0067-v2.5.0-fix-policy-support-timeouts.patch
Patch68: 0068-v2.5.0-fix-cli-policy-allow-timeout-with-ingress-zon.patch
Patch69: 0069-v2.5.0-test-policy-verify-timeout-works.patch
BuildArch: noarch
BuildRequires: autoconf
BuildRequires: automake
@ -276,6 +297,10 @@ rm -rf %{buildroot}%{_datadir}/firewalld/testsuite
%{_mandir}/man1/firewall-config*.1*
%changelog
* Fri Jul 10 2026 Eric Garver <egarver@redhat.com> - 1.3.4-19
- fix(zone): forward: support timeout
- fix(policy): support timeouts
* Tue Dec 02 2025 Eric Garver <egarver@redhat.com> - 1.3.4-18
- fix(policy): allow-host-ipv6: allow MLD packets