diff --git a/SOURCES/RHEL-152316-portblock-check-inverse-action.patch b/SOURCES/RHEL-152316-portblock-check-inverse-action.patch new file mode 100644 index 0000000..bbba366 --- /dev/null +++ b/SOURCES/RHEL-152316-portblock-check-inverse-action.patch @@ -0,0 +1,156 @@ +--- a/heartbeat/portblock 2026-02-27 08:43:50.813925268 +0100 ++++ b/heartbeat/portblock 2026-02-27 08:44:40.481824601 +0100 +@@ -29,12 +29,17 @@ + OCF_RESKEY_direction_default="in" + OCF_RESKEY_action_default="" + OCF_RESKEY_method_default="drop" +-OCF_RESKEY_status_check_default="rule" + OCF_RESKEY_ip_default="0.0.0.0/0" + OCF_RESKEY_reset_local_on_unblock_stop_default="false" + OCF_RESKEY_tickle_dir_default="" + OCF_RESKEY_sync_script_default="" + ++if ocf_is_ms; then ++ OCF_RESKEY_status_check_default="rule" ++else ++ OCF_RESKEY_status_check_default="pseudo" ++fi ++ + : ${OCF_RESKEY_protocol=${OCF_RESKEY_protocol_default}} + : ${OCF_RESKEY_portno=${OCF_RESKEY_portno_default}} + : ${OCF_RESKEY_direction=${OCF_RESKEY_direction_default}} +@@ -401,6 +406,10 @@ + done + } + ++# A long time ago, these messages needed to go to stdout, ++# "running" / "OK" being the trigger string ++# for heartbeat in haresources mode. ++# Now they are still useful for debugging. + SayActive() + { + ocf_log debug "$CMD $method rule [$*] is running (OK)" +@@ -416,6 +425,11 @@ + ocf_log debug "$CMD $method rule [$*] is inactive" + } + ++SayConsideredInactive() ++{ ++ ocf_log debug "$CMD $method rule [$*] considered to be inactive" ++} ++ + #IptablesStatus {udp|tcp} portno,portno ip {in|out|both} {block|unblock} + IptablesStatus() { + local rc +@@ -441,8 +455,17 @@ + fi + ;; + *) +- SayInactive $* +- rc=$OCF_NOT_RUNNING ++ if [ "$OCF_RESKEY_status_check" != "rule" ] \ ++ && test -e "$state_file" && test "$inverse_state_file" -nt "$state_file"; then ++ # rule present, action=unblock, unblock statefile present, ++ # block state file more recent. ++ # apparently an unusual setup: unblock first, block later ++ SayConsideredActive $* ++ rc=$OCF_SUCCESS ++ else ++ SayInactive $* ++ rc=$OCF_NOT_RUNNING ++ fi + ;; + esac + elif [ "$OCF_RESKEY_status_check" = "rule" ]; then +@@ -454,6 +477,7 @@ + *) + SayActive $* + if [ "$__OCF_ACTION" = "monitor" ] && [ "$promotion_score" = "$SCORE_PROMOTED" ]; then ++ save_tcp_connections + rc=$OCF_RUNNING_MASTER + else + rc=$OCF_SUCCESS +@@ -463,7 +487,10 @@ + else + case $5 in + block) +- if ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" status; then ++ if test -e "$state_file" && test "$inverse_state_file" -nt "$state_file"; then ++ # rule NOT present, action=block, block state file present, ++ # unblock state file more recent. ++ # expected setup: block first, unblock later + SayConsideredActive $* + rc=$OCF_SUCCESS + else +@@ -472,13 +499,15 @@ + fi + ;; + *) +- if ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" status; then ++ if test -e "$state_file" ; then ++ # rule NOT present, action=unblock, unblock state file present + SayActive $* +- #This is only run on real monitor events. ++ # This is only run on real monitor events (state file present). + save_tcp_connections + rc=$OCF_SUCCESS + else +- SayInactive $* ++ # rule NOT present, action=unblock, unblock state file NOT present ++ SayConsideredInactive $* + rc=$OCF_NOT_RUNNING + fi + ;; +@@ -562,7 +591,7 @@ + #IptablesStart {udp|tcp} portno,portno ip {in|out|both} {block|unblock} + IptablesStart() + { +- ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" start ++ ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" start "$state_file" + case $5 in + block) IptablesBLOCK "$@" + rc=$? +@@ -584,7 +613,8 @@ + #IptablesStop {udp|tcp} portno,portno ip {in|out|both} {block|unblock} + IptablesStop() + { +- ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" stop ++ ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" stop "$state_file" ++ + case $5 in + block) IptablesUNBLOCK "$@" + rc=$? +@@ -797,6 +827,33 @@ + + IptablesValidateAll + ++# State file name for ha_pseudo_resource ++# ++# The expected usage of this agent is to pair a "block" with an "unblock", ++# and order startup and configuration of some service between these. ++# ++# The established idiom is to have two separate instances with inverse actions. ++# To "reliably" report the status of "block" during a monitor action, ++# it is not sufficient to check the existence of the blocking rule. ++# ++# It is also insufficient to rely on the pseudo resource state file ++# of this instance only. ++# ++# To know our actual expectation, we need to check the state file of the ++# "inverse" instance as well. ++# ++# Because we don't know the OCF_RESOURCE_INSTANCE value of the other instance, ++# we override the state file name for both instances to something derived from ++# our parameters. ++# ++# This should give use the same "global state" view as the "promotion score" ++# does for the promotable clone variant of this agent. ++# ++[ "$action" = block ] && inverse_action=unblock || inverse_action=block ++state_file_base=$(echo "portblock_${protocol}_${portno}_${ip}_${direction}" | tr -c '0-9a-zA-Z._' _) ++state_file=${HA_RSCTMP}/${state_file_base}_${action} ++inverse_state_file=${HA_RSCTMP}/${state_file_base}_${inverse_action} ++ + case $__OCF_ACTION in + start) + IptablesStart "$protocol" "$portno" "$ip" "$direction" "$action" diff --git a/SPECS/resource-agents.spec b/SPECS/resource-agents.spec index 0ad3e46..ca358a9 100644 --- a/SPECS/resource-agents.spec +++ b/SPECS/resource-agents.spec @@ -73,7 +73,7 @@ Name: resource-agents Summary: Open Source HA Reusable Cluster Resource Scripts Version: 4.9.0 -Release: 54%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}.29 +Release: 54%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}.30 License: GPLv2+ and LGPLv2+ URL: https://github.com/ClusterLabs/resource-agents %if 0%{?fedora} || 0%{?centos_version} || 0%{?rhel} @@ -181,6 +181,7 @@ Patch84: RHEL-116150-3-portblock-fixes-add-method-and-status_check-parameters.pa Patch85: RHEL-124815-db2-fix-variable-name.patch Patch86: RHEL-102979-1-nfsserver-support-non-clustered-kerberized-mounts.patch Patch87: RHEL-102979-2-nfsserver-fix-error-message.patch +Patch88: RHEL-152316-portblock-check-inverse-action.patch # bundle patches Patch1000: 7-gcp-bundled.patch @@ -457,6 +458,7 @@ exit 1 %patch -p1 -P 85 %patch -p1 -P 86 %patch -p1 -P 87 +%patch -p1 -P 88 chmod 755 heartbeat/nova-compute-wait chmod 755 heartbeat/NovaEvacuate @@ -1053,6 +1055,12 @@ ccs_update_schema > /dev/null 2>&1 ||: %{_usr}/lib/ocf/lib/heartbeat/OCF_*.pm %changelog +* Fri Feb 27 2026 Oyvind Albrigtsen - 4.9.0-54.30 +- portblock: check inverse action state file for non-promotable + resources to avoid issues when doing e.g. block followed by unblock + + Resolves: RHEL-152316 + * Thu Feb 5 2026 Oyvind Albrigtsen - 4.9.0-54.29 - bundled urllib3: fix issue with CVE-2026-21441 patch