Compare commits
No commits in common. "c8" and "c8-beta" have entirely different histories.
@ -1,31 +0,0 @@
|
||||
From 8dc0d9b43343919edf4f4011ceecfd6b6765b4a4 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Gaillot <kgaillot@redhat.com>
|
||||
Date: Wed, 8 May 2024 11:18:50 -0500
|
||||
Subject: [PATCH] Low: libcib: avoid memory leak in async calls
|
||||
|
||||
Never in a release
|
||||
---
|
||||
lib/cib/cib_native.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/cib/cib_native.c b/lib/cib/cib_native.c
|
||||
index 0e502155bc..b014223112 100644
|
||||
--- a/lib/cib/cib_native.c
|
||||
+++ b/lib/cib/cib_native.c
|
||||
@@ -94,9 +94,10 @@ cib_native_perform_op_delegate(cib_t *cib, const char *op, const char *host,
|
||||
|
||||
if (!(call_options & cib_sync_call)) {
|
||||
crm_trace("Async call, returning %d", cib->call_id);
|
||||
- CRM_CHECK(cib->call_id != 0, return -ENOMSG);
|
||||
- free_xml(op_reply);
|
||||
- return cib->call_id;
|
||||
+ CRM_CHECK(cib->call_id != 0,
|
||||
+ rc = -ENOMSG; goto done);
|
||||
+ rc = cib->call_id;
|
||||
+ goto done;
|
||||
}
|
||||
|
||||
rc = pcmk_ok;
|
||||
--
|
||||
2.41.0
|
||||
|
||||
@ -1,121 +0,0 @@
|
||||
From d7c233090057d4f660fa458a2ff97896b15ea951 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Thu, 11 Jul 2024 12:43:49 -0700
|
||||
Subject: [PATCH] Refactor: various: Don't set cluster-layer node ID as XML ID
|
||||
|
||||
Currently, we call the pcmk__xe_set_id() function using a stringified
|
||||
version of the numeric cluster-layer node ID. However, pcmk__xe_set_id()
|
||||
tries to sanitize its input to a valid XML ID. An XML ID cannot begin
|
||||
with a digit.
|
||||
|
||||
crm_xml_set_id() does not sanitize comprehensively, and in particular,
|
||||
it does not care whether its argument begins with a digit. So the
|
||||
current code doesn't cause a problem.
|
||||
|
||||
Still, as a best practice, set the PCMK_XA_ID attribute using
|
||||
crm_xml_add_ll() instead.
|
||||
|
||||
Ref T848
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
daemons/controld/controld_messages.c | 6 +++++-
|
||||
lib/cluster/corosync.c | 2 +-
|
||||
lib/common/ipc_client.c | 2 +-
|
||||
lib/common/ipc_controld.c | 9 ++++++---
|
||||
tools/crm_node.c | 4 ++--
|
||||
5 files changed, 15 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/daemons/controld/controld_messages.c b/daemons/controld/controld_messages.c
|
||||
index bd5237e..0b0f25b 100644
|
||||
--- a/daemons/controld/controld_messages.c
|
||||
+++ b/daemons/controld/controld_messages.c
|
||||
@@ -893,7 +893,11 @@ handle_node_info_request(const xmlNode *msg)
|
||||
pcmk_is_set(controld_globals.flags,
|
||||
controld_has_quorum));
|
||||
|
||||
- // Check whether client requested node info by ID and/or name
|
||||
+ /* Check whether client requested node info by ID and/or name
|
||||
+ *
|
||||
+ * @TODO A Corosync-layer node ID is of type uint32_t. We should be able to
|
||||
+ * handle legitimate node IDs greater than INT_MAX, but currently we do not.
|
||||
+ */
|
||||
crm_element_value_int(msg, XML_ATTR_ID, &node_id);
|
||||
if (node_id < 0) {
|
||||
node_id = 0;
|
||||
diff --git a/lib/cluster/corosync.c b/lib/cluster/corosync.c
|
||||
index 374250f..fc33cce 100644
|
||||
--- a/lib/cluster/corosync.c
|
||||
+++ b/lib/cluster/corosync.c
|
||||
@@ -650,7 +650,7 @@ pcmk__corosync_add_nodes(xmlNode *xml_parent)
|
||||
if (xml_parent) {
|
||||
xmlNode *node = create_xml_node(xml_parent, XML_CIB_TAG_NODE);
|
||||
|
||||
- crm_xml_set_id(node, "%u", nodeid);
|
||||
+ crm_xml_add_ll(node, XML_ATTR_ID, (long long) nodeid);
|
||||
crm_xml_add(node, XML_ATTR_UNAME, name);
|
||||
}
|
||||
}
|
||||
diff --git a/lib/common/ipc_client.c b/lib/common/ipc_client.c
|
||||
index 5e64e23..7696a69 100644
|
||||
--- a/lib/common/ipc_client.c
|
||||
+++ b/lib/common/ipc_client.c
|
||||
@@ -769,7 +769,7 @@ create_purge_node_request(const pcmk_ipc_api_t *api, const char *node_name,
|
||||
request = create_request(CRM_OP_RM_NODE_CACHE, NULL, NULL,
|
||||
pcmk_ipc_name(api, false), client, NULL);
|
||||
if (nodeid > 0) {
|
||||
- crm_xml_set_id(request, "%lu", (unsigned long) nodeid);
|
||||
+ crm_xml_add_ll(request, XML_ATTR_ID, (unsigned long) nodeid);
|
||||
}
|
||||
crm_xml_add(request, XML_ATTR_UNAME, node_name);
|
||||
break;
|
||||
diff --git a/lib/common/ipc_controld.c b/lib/common/ipc_controld.c
|
||||
index 8e2016e..e4284f5 100644
|
||||
--- a/lib/common/ipc_controld.c
|
||||
+++ b/lib/common/ipc_controld.c
|
||||
@@ -9,9 +9,12 @@
|
||||
|
||||
#include <crm_internal.h>
|
||||
|
||||
-#include <stdio.h>
|
||||
-#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
+#include <inttypes.h> // PRIu32
|
||||
+#include <stdbool.h>
|
||||
+#include <stdint.h> // uint32_t
|
||||
+#include <stdio.h>
|
||||
+
|
||||
#include <libxml/tree.h>
|
||||
|
||||
#include <crm/crm.h>
|
||||
@@ -412,7 +415,7 @@ pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
|
||||
return EINVAL;
|
||||
}
|
||||
if (nodeid > 0) {
|
||||
- crm_xml_set_id(request, "%lu", (unsigned long) nodeid);
|
||||
+ crm_xml_add_ll(request, XML_ATTR_ID, (unsigned long) nodeid);
|
||||
}
|
||||
|
||||
rc = send_controller_request(api, request, true);
|
||||
diff --git a/tools/crm_node.c b/tools/crm_node.c
|
||||
index 1e7ce6c..ad8c459 100644
|
||||
--- a/tools/crm_node.c
|
||||
+++ b/tools/crm_node.c
|
||||
@@ -552,7 +552,7 @@ remove_from_section(cib_t *cib, const char *element, const char *section,
|
||||
}
|
||||
crm_xml_add(xml, XML_ATTR_UNAME, node_name);
|
||||
if (node_id > 0) {
|
||||
- crm_xml_set_id(xml, "%ld", node_id);
|
||||
+ crm_xml_add_ll(xml, XML_ATTR_ID, node_id);
|
||||
}
|
||||
rc = cib->cmds->remove(cib, section, xml, cib_transaction);
|
||||
free_xml(xml);
|
||||
@@ -691,7 +691,7 @@ purge_node_from_fencer(const char *node_name, long node_id)
|
||||
cmd = create_request(CRM_OP_RM_NODE_CACHE, NULL, NULL, "stonith-ng",
|
||||
crm_system_name, NULL);
|
||||
if (node_id > 0) {
|
||||
- crm_xml_set_id(cmd, "%ld", node_id);
|
||||
+ crm_xml_add_ll(cmd, XML_ATTR_ID, node_id);
|
||||
}
|
||||
crm_xml_add(cmd, XML_ATTR_UNAME, node_name);
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
From 22e093a5bff608c86d0ea68588078ca747a6d945 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Thu, 11 Jul 2024 12:29:34 -0700
|
||||
Subject: [PATCH] Fix: tools: crm_node -i must initialize nodeid before passing
|
||||
pointer
|
||||
|
||||
This is a regression introduced in 2.1.7 via a27f099.
|
||||
|
||||
Currently, crm_node -i passes a pointer to the uninitialized uint32_t
|
||||
nodeid variable, to pcmk__query_node_info(). Since the pointer is
|
||||
non-NULL, pcmk__query_node_info() dereferences it. Whatever garbage
|
||||
value resides there gets passed as the ID to query.
|
||||
|
||||
The controller parses the node ID from the request as an int. If the
|
||||
garbage value is greater than INT_MAX, it overflows to a negative int
|
||||
value, and the controller (in handle_node_info_request()) defaults it to
|
||||
0. In that case, there's no problem: we search for the local node name
|
||||
instead of the garbage node ID.
|
||||
|
||||
If the garbage value is less than or equal to INT_MAX, we search for it
|
||||
directly. We won't find a matching node unless one happens to exist with
|
||||
that garbage node ID. In the case of no match, crm_node -i outputs "Node
|
||||
is not known to cluster" instead of the local node's cluster-layer ID.
|
||||
|
||||
Thanks to Artur Novik for the report:
|
||||
https://lists.clusterlabs.org/pipermail/users/2024-July/036270.html
|
||||
|
||||
Fixes T847
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
lib/pacemaker/pcmk_cluster_queries.c | 22 +++++++++++-----------
|
||||
tools/crm_node.c | 2 +-
|
||||
2 files changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/lib/pacemaker/pcmk_cluster_queries.c b/lib/pacemaker/pcmk_cluster_queries.c
|
||||
index 3229fae3eff..8404584580e 100644
|
||||
--- a/lib/pacemaker/pcmk_cluster_queries.c
|
||||
+++ b/lib/pacemaker/pcmk_cluster_queries.c
|
||||
@@ -586,25 +586,25 @@ pcmk_designated_controller(xmlNodePtr *xml, unsigned int message_timeout_ms)
|
||||
* the controller
|
||||
*
|
||||
* \param[in,out] out Output object
|
||||
- * \param[in,out] node_id ID of node whose name to get. If \p NULL
|
||||
- * or 0, get the local node name. If not
|
||||
- * \p NULL, store the true node ID here on
|
||||
+ * \param[in,out] node_id ID of node whose info to get. If \p NULL
|
||||
+ * or 0, get the local node's info. If not
|
||||
+ * \c NULL, store the true node ID here on
|
||||
* success.
|
||||
- * \param[out] node_name If not \p NULL, where to store the node
|
||||
+ * \param[out] node_name If not \c NULL, where to store the node
|
||||
* name
|
||||
- * \param[out] uuid If not \p NULL, where to store the node
|
||||
+ * \param[out] uuid If not \c NULL, where to store the node
|
||||
* UUID
|
||||
- * \param[out] state If not \p NULL, where to store the
|
||||
+ * \param[out] state If not \c NULL, where to store the
|
||||
* membership state
|
||||
- * \param[out] is_remote If not \p NULL, where to store whether the
|
||||
+ * \param[out] is_remote If not \c NULL, where to store whether the
|
||||
* node is a Pacemaker Remote node
|
||||
- * \param[out] have_quorum If not \p NULL, where to store whether the
|
||||
+ * \param[out] have_quorum If not \c NULL, where to store whether the
|
||||
* node has quorum
|
||||
* \param[in] show_output Whether to show the node info
|
||||
* \param[in] message_timeout_ms How long to wait for a reply from the
|
||||
- * \p pacemaker-controld API. If 0,
|
||||
- * \p pcmk_ipc_dispatch_sync will be used.
|
||||
- * Otherwise, \p pcmk_ipc_dispatch_poll will
|
||||
+ * \c pacemaker-controld API. If 0,
|
||||
+ * \c pcmk_ipc_dispatch_sync will be used.
|
||||
+ * Otherwise, \c pcmk_ipc_dispatch_poll will
|
||||
* be used.
|
||||
*
|
||||
* \return Standard Pacemaker return code
|
||||
diff --git a/tools/crm_node.c b/tools/crm_node.c
|
||||
index d4153605a69..8aa8d3d29c7 100644
|
||||
--- a/tools/crm_node.c
|
||||
+++ b/tools/crm_node.c
|
||||
@@ -434,7 +434,7 @@ run_controller_mainloop(void)
|
||||
static void
|
||||
print_node_id(void)
|
||||
{
|
||||
- uint32_t nodeid;
|
||||
+ uint32_t nodeid = 0;
|
||||
int rc = pcmk__query_node_info(out, &nodeid, NULL, NULL, NULL, NULL, NULL,
|
||||
false, 0);
|
||||
|
||||
@ -1,387 +0,0 @@
|
||||
From 96bb1076281bfe46caab135f24ea24fc02ead388 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 10 Jul 2025 11:15:20 -0400
|
||||
Subject: [PATCH 1/5] Refactor: scheduler: Fix formatting in pe_can_fence.
|
||||
|
||||
---
|
||||
lib/pengine/utils.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
|
||||
index 4055d6d..19cc5a2 100644
|
||||
--- a/lib/pengine/utils.c
|
||||
+++ b/lib/pengine/utils.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2004-2023 the Pacemaker project contributors
|
||||
+ * Copyright 2004-2025 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -63,10 +63,10 @@ pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
|
||||
} else if (scheduler->no_quorum_policy == pcmk_no_quorum_ignore) {
|
||||
return true;
|
||||
|
||||
- } else if(node == NULL) {
|
||||
+ } else if (node == NULL) {
|
||||
return false;
|
||||
|
||||
- } else if(node->details->online) {
|
||||
+ } else if (node->details->online) {
|
||||
crm_notice("We can fence %s without quorum because they're in our membership",
|
||||
pe__node_name(node));
|
||||
return true;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
From a69d33bb78458e5bb19d07dacc91754856418649 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Fri, 28 Mar 2025 15:08:56 -0400
|
||||
Subject: [PATCH 2/5] Med: scheduler: Don't always fence online remote nodes.
|
||||
|
||||
Let's assume you have a cluster configured as follows:
|
||||
|
||||
* Three nodes, plus one Pacemaker Remote node.
|
||||
* At least two NICs on each node.
|
||||
* Multiple layers of fencing, including fence_kdump.
|
||||
* The timeout for fence_kdump is set higher on the real nodes than it is
|
||||
on the remote node.
|
||||
* A resource is configured that can only be run on the remote node.
|
||||
|
||||
Now, let's assume that the node running the connection resource for the
|
||||
remote node is disconnect from the rest of the cluster. In testing,
|
||||
this disconnection was done by bringing one network interface down.
|
||||
|
||||
Due to the fence timeouts, the following things will occur:
|
||||
|
||||
* The node whose interface was brought down will split off into its own
|
||||
cluster partition without quorum, while the other two nodes maintain
|
||||
quorum.
|
||||
* The partition with quorum will restart the remote node resource on
|
||||
another real node in the partition.
|
||||
* The node by itself will be fenced. However, due to the long
|
||||
fence_kdump timeout, it will continue to make decisions regarding
|
||||
resources.
|
||||
* The node by itself will re-assign resources, including the remote
|
||||
connection resource. This resource will be assigned back to the same
|
||||
node again.
|
||||
* The node by itself will decide to fence the remote node, which will
|
||||
hit the "in our membership" clause of pe_can_fence. This is because
|
||||
remote nodes are marked as online when they are assigned, not when
|
||||
they are actually running.
|
||||
* When the fence_kdump timeout expires, the node by itself will fence
|
||||
the remote node. This succeeds because there is still a secondary
|
||||
network connection it can use. This fencing will succeed, causing the
|
||||
remote node to reboot and then causing a loss of service.
|
||||
* The node by itself will then be fenced.
|
||||
|
||||
The bug to me seems to be that the remote resource is marked as online
|
||||
when it isn't yet. I think with that changed, all the other remote
|
||||
fencing related code would then work as intended. However, it probably
|
||||
has to remain as-is in order to schedule resources on the remote node -
|
||||
resources probably can't be assigned to an offline node. Making changes
|
||||
in pe_can_fence seems like the least invasive way to deal with this
|
||||
problem.
|
||||
|
||||
I also think this probably has probably been here for a very long time -
|
||||
perhaps always - but we just haven't seen it due to the number of things
|
||||
that have to be configured before it can show up. In particular, the
|
||||
fencing timeouts and secondary network connection are what allow this
|
||||
behavior to happen.
|
||||
|
||||
I can't think of a good reason why a node without quorum would ever want
|
||||
to fence a remote node, especially if the connection resource has been
|
||||
moved to the quorate node.
|
||||
|
||||
My fix here therefore is just to test whether there is another node it
|
||||
could have been moved to and if so, don't fence it.
|
||||
|
||||
Fixes T978
|
||||
Fixes RHEL-84018
|
||||
---
|
||||
lib/pengine/utils.c | 33 +++++++++++++++++++++++++++++++++
|
||||
1 file changed, 33 insertions(+)
|
||||
|
||||
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
|
||||
index 19cc5a2..402cecd 100644
|
||||
--- a/lib/pengine/utils.c
|
||||
+++ b/lib/pengine/utils.c
|
||||
@@ -67,6 +67,39 @@ pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
|
||||
return false;
|
||||
|
||||
} else if (node->details->online) {
|
||||
+ /* Remote nodes are marked online when we assign their resource to a
|
||||
+ * node, not when they are actually started (see remote_connection_assigned)
|
||||
+ * so the above test by itself isn't good enough.
|
||||
+ */
|
||||
+ if (pe__is_remote_node(node)) {
|
||||
+ /* If we're on a system without quorum, it's entirely possible that
|
||||
+ * the remote resource was automatically moved to a node on the
|
||||
+ * partition with quorum. We can't tell that from this node - the
|
||||
+ * best we can do is check if it's possible for the resource to run
|
||||
+ * on another node in the partition with quorum. If so, it has
|
||||
+ * likely been moved and we shouldn't fence it.
|
||||
+ *
|
||||
+ * NOTE: This condition appears to only come up in very limited
|
||||
+ * circumstances. It at least requires some very lengthy fencing
|
||||
+ * timeouts set, some way for fencing to still take place (a second
|
||||
+ * NIC is how I've reproduced it in testing, but fence_scsi or
|
||||
+ * sbd could work too), and a resource that runs on the remote node.
|
||||
+ */
|
||||
+ pcmk_resource_t *rsc = node->details->remote_rsc;
|
||||
+ pcmk_node_t *n = NULL;
|
||||
+ GHashTableIter iter;
|
||||
+
|
||||
+ g_hash_table_iter_init(&iter, rsc->allowed_nodes);
|
||||
+ while (g_hash_table_iter_next(&iter, NULL, (void **) &n)) {
|
||||
+ /* A node that's not online according to this non-quorum node
|
||||
+ * is a node that's in another partition.
|
||||
+ */
|
||||
+ if (!n->details->online) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
crm_notice("We can fence %s without quorum because they're in our membership",
|
||||
pe__node_name(node));
|
||||
return true;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
From 7d503928c48b67da0bd06bccaa080f0309f7be90 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 10 Jul 2025 11:25:05 -0400
|
||||
Subject: [PATCH 3/5] Med: scheduler: Require a cluster option for new remote
|
||||
fencing behavior.
|
||||
|
||||
We don't have a ton of confidence that the previous patch is the right
|
||||
thing to do for everyone, so we are going to hide it behind this
|
||||
undocumented cluster config option. By default, if the option is
|
||||
missing (or is set to "true"), the existing remote fencing behavior will
|
||||
be what happens. That is, a node without quorum will be allowed to
|
||||
fence remote nodes in the same partition even if they've been restarted
|
||||
elsewhere.
|
||||
|
||||
However, with fence-remote-without-quorum="false", we will check to see
|
||||
if the remote node could possibly have been started on another node and
|
||||
if so, it will not be fenced.
|
||||
---
|
||||
cts/cli/regression.daemons.exp | 5 +++++
|
||||
include/crm/common/options_internal.h | 5 ++++-
|
||||
include/crm/common/scheduler.h | 7 ++++++-
|
||||
lib/common/options.c | 13 ++++++++++++-
|
||||
lib/pengine/unpack.c | 12 +++++++++++-
|
||||
lib/pengine/utils.c | 6 +++++-
|
||||
6 files changed, 43 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/cts/cli/regression.daemons.exp b/cts/cli/regression.daemons.exp
|
||||
index 543d62f..678cb62 100644
|
||||
--- a/cts/cli/regression.daemons.exp
|
||||
+++ b/cts/cli/regression.daemons.exp
|
||||
@@ -292,6 +292,11 @@
|
||||
<shortdesc lang="en">Whether the cluster should check for active resources during start-up</shortdesc>
|
||||
<content type="boolean" default=""/>
|
||||
</parameter>
|
||||
+ <parameter name="fence-remote-without-quorum">
|
||||
+ <longdesc lang="en">By default, inquorate nodes can fence Pacemaker Remote nodes that are part of its partition regardless of whether the resource was successfully restarted elsewhere. If false, an additional check will be added to only fence remote nodes if the cluster thinks they were unable to be restarted.</longdesc>
|
||||
+ <shortdesc lang="en">*** Advanced Use Only *** Whether remote nodes can be fenced without quorum</shortdesc>
|
||||
+ <content type="boolean" default=""/>
|
||||
+ </parameter>
|
||||
<parameter name="stonith-enabled">
|
||||
<longdesc lang="en">If false, unresponsive nodes are immediately assumed to be harmless, and resources that were active on them may be recovered elsewhere. This can result in a "split-brain" situation, potentially leading to data loss and/or service unavailability.</longdesc>
|
||||
<shortdesc lang="en">*** Advanced Use Only *** Whether nodes may be fenced as part of recovery</shortdesc>
|
||||
diff --git a/include/crm/common/options_internal.h b/include/crm/common/options_internal.h
|
||||
index b727a58..95edc53 100644
|
||||
--- a/include/crm/common/options_internal.h
|
||||
+++ b/include/crm/common/options_internal.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2006-2023 the Pacemaker project contributors
|
||||
+ * Copyright 2006-2025 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -167,5 +167,8 @@ bool pcmk__valid_sbd_timeout(const char *value);
|
||||
#define PCMK__VALUE_RED "red"
|
||||
#define PCMK__VALUE_UNFENCING "unfencing"
|
||||
#define PCMK__VALUE_YELLOW "yellow"
|
||||
+
|
||||
+// Cluster options
|
||||
+#define PCMK__OPT_FENCE_REMOTE_WITHOUT_QUORUM "fence-remote-without-quorum"
|
||||
|
||||
#endif // PCMK__OPTIONS_INTERNAL__H
|
||||
diff --git a/include/crm/common/scheduler.h b/include/crm/common/scheduler.h
|
||||
index 96f9a62..259fa5b 100644
|
||||
--- a/include/crm/common/scheduler.h
|
||||
+++ b/include/crm/common/scheduler.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2004-2023 the Pacemaker project contributors
|
||||
+ * Copyright 2004-2025 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -184,6 +184,11 @@ struct pe_working_set_s {
|
||||
|
||||
int stonith_timeout; //!< Value of stonith-timeout property
|
||||
enum pe_quorum_policy no_quorum_policy; //!< Response to loss of quorum
|
||||
+
|
||||
+ // Can Pacemaker Remote nodes be fenced even from a node that doesn't
|
||||
+ // have quorum?
|
||||
+ bool fence_remote_without_quorum;
|
||||
+
|
||||
GHashTable *config_hash; //!< Cluster properties
|
||||
|
||||
//!< Ticket constraints unpacked from ticket state
|
||||
diff --git a/lib/common/options.c b/lib/common/options.c
|
||||
index 13d58e3..96f059c 100644
|
||||
--- a/lib/common/options.c
|
||||
+++ b/lib/common/options.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2004-2022 the Pacemaker project contributors
|
||||
+ * Copyright 2004-2025 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -232,6 +232,17 @@ static pcmk__cluster_option_t cluster_options[] = {
|
||||
},
|
||||
|
||||
// Fencing-related options
|
||||
+ { PCMK__OPT_FENCE_REMOTE_WITHOUT_QUORUM, NULL, "boolean", NULL,
|
||||
+ XML_BOOLEAN_TRUE, pcmk__valid_boolean,
|
||||
+ pcmk__opt_context_schedulerd,
|
||||
+ N_("*** Advanced Use Only *** "
|
||||
+ "Whether remote nodes can be fenced without quorum"),
|
||||
+ N_("By default, inquorate nodes can fence Pacemaker Remote nodes that "
|
||||
+ "are part of its partition regardless of whether the resource "
|
||||
+ "was successfully restarted elsewhere. If false, an additional "
|
||||
+ "check will be added to only fence remote nodes if the cluster "
|
||||
+ "thinks they were unable to be restarted.")
|
||||
+ },
|
||||
{
|
||||
"stonith-enabled", NULL, "boolean", NULL,
|
||||
XML_BOOLEAN_TRUE, pcmk__valid_boolean,
|
||||
diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c
|
||||
index d484e93..e96b978 100644
|
||||
--- a/lib/pengine/unpack.c
|
||||
+++ b/lib/pengine/unpack.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2004-2023 the Pacemaker project contributors
|
||||
+ * Copyright 2004-2025 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -435,6 +435,16 @@ unpack_config(xmlNode *config, pcmk_scheduler_t *scheduler)
|
||||
* 1000));
|
||||
}
|
||||
|
||||
+ value = pcmk__cluster_option(config_hash,
|
||||
+ PCMK__OPT_FENCE_REMOTE_WITHOUT_QUORUM);
|
||||
+ if ((value != NULL) && !crm_is_true(value)) {
|
||||
+ crm_warn(PCMK__OPT_FENCE_REMOTE_WITHOUT_QUORUM " disabled - remote "
|
||||
+ "nodes may not be fenced in inquorate partition");
|
||||
+ scheduler->fence_remote_without_quorum = false;
|
||||
+ } else {
|
||||
+ scheduler->fence_remote_without_quorum = true;
|
||||
+ }
|
||||
+
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
|
||||
index 402cecd..f25717d 100644
|
||||
--- a/lib/pengine/utils.c
|
||||
+++ b/lib/pengine/utils.c
|
||||
@@ -70,8 +70,12 @@ pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
|
||||
/* Remote nodes are marked online when we assign their resource to a
|
||||
* node, not when they are actually started (see remote_connection_assigned)
|
||||
* so the above test by itself isn't good enough.
|
||||
+ *
|
||||
+ * This is experimental behavior, so the user has to opt into it by
|
||||
+ * adding fence-remote-without-quorum="false" to their CIB.
|
||||
*/
|
||||
- if (pe__is_remote_node(node)) {
|
||||
+ if (pe__is_remote_node(node)
|
||||
+ && !scheduler->fence_remote_without_quorum) {
|
||||
/* If we're on a system without quorum, it's entirely possible that
|
||||
* the remote resource was automatically moved to a node on the
|
||||
* partition with quorum. We can't tell that from this node - the
|
||||
--
|
||||
2.43.0
|
||||
|
||||
From 9ad7c0157cb0ac271ddf9b401e072a7d00de05de Mon Sep 17 00:00:00 2001
|
||||
From: "Gao,Yan" <ygao@suse.com>
|
||||
Date: Thu, 10 Apr 2025 12:51:57 +0200
|
||||
Subject: [PATCH 4/5] Refactor: libcrmcommon: move the new struct member to the
|
||||
end for backward compatibility
|
||||
|
||||
Commit f342b77561 broke backward compatibility by inserting the new
|
||||
member `fence_remote_without_quorum` into the middle of the
|
||||
`pe_working_set_s` struct.
|
||||
---
|
||||
include/crm/common/scheduler.h | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/scheduler.h b/include/crm/common/scheduler.h
|
||||
index 259fa5b..4baee09 100644
|
||||
--- a/include/crm/common/scheduler.h
|
||||
+++ b/include/crm/common/scheduler.h
|
||||
@@ -185,10 +185,6 @@ struct pe_working_set_s {
|
||||
int stonith_timeout; //!< Value of stonith-timeout property
|
||||
enum pe_quorum_policy no_quorum_policy; //!< Response to loss of quorum
|
||||
|
||||
- // Can Pacemaker Remote nodes be fenced even from a node that doesn't
|
||||
- // have quorum?
|
||||
- bool fence_remote_without_quorum;
|
||||
-
|
||||
GHashTable *config_hash; //!< Cluster properties
|
||||
|
||||
//!< Ticket constraints unpacked from ticket state
|
||||
@@ -234,6 +230,10 @@ struct pe_working_set_s {
|
||||
void *priv; //!< For Pacemaker use only
|
||||
|
||||
guint node_pending_timeout; //!< Pending join times out after this (ms)
|
||||
+
|
||||
+ // Can Pacemaker Remote nodes be fenced even from a node that doesn't
|
||||
+ // have quorum?
|
||||
+ bool fence_remote_without_quorum;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
--
|
||||
2.43.0
|
||||
|
||||
From 8159779e13da5ddd2a6ce77542e945abb4c2663d Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Tue, 29 Apr 2025 12:49:45 -0400
|
||||
Subject: [PATCH 5/5] Refactor: scheduler: Lower fencing log message to debug
|
||||
level.
|
||||
|
||||
Most other things in unpack_config are logged at debug or trace level.
|
||||
Having the fencing message at the warn level makes it come up quite
|
||||
often.
|
||||
---
|
||||
lib/pengine/unpack.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c
|
||||
index e96b978..5d124a3 100644
|
||||
--- a/lib/pengine/unpack.c
|
||||
+++ b/lib/pengine/unpack.c
|
||||
@@ -438,8 +438,8 @@ unpack_config(xmlNode *config, pcmk_scheduler_t *scheduler)
|
||||
value = pcmk__cluster_option(config_hash,
|
||||
PCMK__OPT_FENCE_REMOTE_WITHOUT_QUORUM);
|
||||
if ((value != NULL) && !crm_is_true(value)) {
|
||||
- crm_warn(PCMK__OPT_FENCE_REMOTE_WITHOUT_QUORUM " disabled - remote "
|
||||
- "nodes may not be fenced in inquorate partition");
|
||||
+ crm_debug(PCMK__OPT_FENCE_REMOTE_WITHOUT_QUORUM " disabled - remote "
|
||||
+ "nodes may not be fenced in inquorate partition");
|
||||
scheduler->fence_remote_without_quorum = false;
|
||||
} else {
|
||||
scheduler->fence_remote_without_quorum = true;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@ -1,303 +0,0 @@
|
||||
From 581ef435f7b6b0fde76663069ec63b3b4fb4b067 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 27 Aug 2025 10:41:13 -0400
|
||||
Subject: [PATCH 1/5] Refactor: libcrmcommon: Rearrange the queue_len check.
|
||||
|
||||
Check if the queue length is 0 first and return, which allows everything
|
||||
else to be un-indented one level.
|
||||
---
|
||||
lib/common/ipc_server.c | 47 ++++++++++++++++++++---------------------
|
||||
1 file changed, 23 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/lib/common/ipc_server.c b/lib/common/ipc_server.c
|
||||
index 5cd7e70..ee8ae9e 100644
|
||||
--- a/lib/common/ipc_server.c
|
||||
+++ b/lib/common/ipc_server.c
|
||||
@@ -535,34 +535,33 @@ crm_ipcs_flush_events(pcmk__client_t *c)
|
||||
pcmk_rc_str(rc), (long long) qb_rc);
|
||||
}
|
||||
|
||||
- if (queue_len) {
|
||||
-
|
||||
- /* Allow clients to briefly fall behind on processing incoming messages,
|
||||
- * but drop completely unresponsive clients so the connection doesn't
|
||||
- * consume resources indefinitely.
|
||||
- */
|
||||
- if (queue_len > QB_MAX(c->queue_max, PCMK_IPC_DEFAULT_QUEUE_MAX)) {
|
||||
- if ((c->queue_backlog <= 1) || (queue_len < c->queue_backlog)) {
|
||||
- /* Don't evict for a new or shrinking backlog */
|
||||
- crm_warn("Client with process ID %u has a backlog of %u messages "
|
||||
- CRM_XS " %p", c->pid, queue_len, c->ipcs);
|
||||
- } else {
|
||||
- crm_err("Evicting client with process ID %u due to backlog of %u messages "
|
||||
- CRM_XS " %p", c->pid, queue_len, c->ipcs);
|
||||
- c->queue_backlog = 0;
|
||||
- qb_ipcs_disconnect(c->ipcs);
|
||||
- return rc;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- c->queue_backlog = queue_len;
|
||||
- delay_next_flush(c, queue_len);
|
||||
-
|
||||
- } else {
|
||||
+ if (queue_len == 0) {
|
||||
/* Event queue is empty, there is no backlog */
|
||||
c->queue_backlog = 0;
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ /* Allow clients to briefly fall behind on processing incoming messages,
|
||||
+ * but drop completely unresponsive clients so the connection doesn't
|
||||
+ * consume resources indefinitely.
|
||||
+ */
|
||||
+ if (queue_len > QB_MAX(c->queue_max, PCMK_IPC_DEFAULT_QUEUE_MAX)) {
|
||||
+ if ((c->queue_backlog <= 1) || (queue_len < c->queue_backlog)) {
|
||||
+ /* Don't evict for a new or shrinking backlog */
|
||||
+ crm_warn("Client with process ID %u has a backlog of %u messages "
|
||||
+ CRM_XS " %p", c->pid, queue_len, c->ipcs);
|
||||
+ } else {
|
||||
+ crm_err("Evicting client with process ID %u due to backlog of %u messages "
|
||||
+ CRM_XS " %p", c->pid, queue_len, c->ipcs);
|
||||
+ c->queue_backlog = 0;
|
||||
+ qb_ipcs_disconnect(c->ipcs);
|
||||
+ return rc;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ c->queue_backlog = queue_len;
|
||||
+ delay_next_flush(c, queue_len);
|
||||
+
|
||||
return rc;
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
From 54fbc6bea137d0642308d49506f13bd84cd2084e Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 27 Aug 2025 11:31:37 -0400
|
||||
Subject: [PATCH 2/5] Refactor: libcrmcommon: Simplify an empty event queue
|
||||
check.
|
||||
|
||||
I find this just a little bit more straightforward to follow.
|
||||
---
|
||||
lib/common/ipc_server.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/common/ipc_server.c b/lib/common/ipc_server.c
|
||||
index ee8ae9e..d24db59 100644
|
||||
--- a/lib/common/ipc_server.c
|
||||
+++ b/lib/common/ipc_server.c
|
||||
@@ -500,10 +500,13 @@ crm_ipcs_flush_events(pcmk__client_t *c)
|
||||
pcmk__ipc_header_t *header = NULL;
|
||||
struct iovec *event = NULL;
|
||||
|
||||
- if (c->event_queue) {
|
||||
- // We don't pop unless send is successful
|
||||
- event = g_queue_peek_head(c->event_queue);
|
||||
+ if ((c->event_queue == NULL) || g_queue_is_empty(c->event_queue)) {
|
||||
+ break;
|
||||
}
|
||||
+
|
||||
+ // We don't pop unless send is successful
|
||||
+ event = g_queue_peek_head(c->event_queue);
|
||||
+
|
||||
if (event == NULL) { // Queue is empty
|
||||
break;
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
From 6446aa1d917be090989860c3a5cc00ea6a311d67 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 27 Aug 2025 11:35:38 -0400
|
||||
Subject: [PATCH 3/5] Refactor: libcrmcommon: Rearrange a few tests in
|
||||
crm_ipcs_flush_events.
|
||||
|
||||
Again, no important code changes here. I just find these a little
|
||||
easier to follow.
|
||||
---
|
||||
lib/common/ipc_server.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/common/ipc_server.c b/lib/common/ipc_server.c
|
||||
index d24db59..c305dfc 100644
|
||||
--- a/lib/common/ipc_server.c
|
||||
+++ b/lib/common/ipc_server.c
|
||||
@@ -486,16 +486,18 @@ crm_ipcs_flush_events(pcmk__client_t *c)
|
||||
|
||||
if (c == NULL) {
|
||||
return rc;
|
||||
+ }
|
||||
|
||||
- } else if (c->event_timer) {
|
||||
+ if (c->event_timer != 0) {
|
||||
/* There is already a timer, wait until it goes off */
|
||||
crm_trace("Timer active for %p - %d", c->ipcs, c->event_timer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
- if (c->event_queue) {
|
||||
+ if (c->event_queue != NULL) {
|
||||
queue_len = g_queue_get_length(c->event_queue);
|
||||
}
|
||||
+
|
||||
while (sent < 100) {
|
||||
pcmk__ipc_header_t *header = NULL;
|
||||
struct iovec *event = NULL;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
From d7576ecb3f51050a21057d86257bf8b8c273e4db Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 27 Aug 2025 13:14:54 -0400
|
||||
Subject: [PATCH 4/5] Feature: libcrmcommon: Be more lenient in evicting IPC
|
||||
clients.
|
||||
|
||||
Each IPC connection has a message queue. If the client is unable to
|
||||
process messages faster than the server is sending them, that queue
|
||||
start to back up. pacemaker enforces a cap on the queue size, and
|
||||
that's adjustable with the cluster-ipc-limit parameter. Once the queue
|
||||
grows beyond that size, the client is assumed to be dead and is evicted
|
||||
so it can be restarted and the queue resources freed.
|
||||
|
||||
However, it's possible that the client is not dead. On clusters with
|
||||
very large numbers of resources (I've tried with 300, but fewer might
|
||||
also cause problems), certain actions can happen that cause a spike in
|
||||
IPC messages. In RHEL-76276, the action that causes this is moving
|
||||
nodes in and out of standby. This spike in messages causes the server
|
||||
to overwhelm the client, which is then evicted.
|
||||
|
||||
My multi-part IPC patches made this even worse, as now if the CIB is so
|
||||
large that it needs to split an IPC message up, there will be more
|
||||
messages than before.
|
||||
|
||||
What this fix does is get rid of the cap on the queue size for pacemaker
|
||||
daemons. As long as the server has been able to send messages to the
|
||||
client, the client is still doing work and shouldn't be evicted. It may
|
||||
just be processing messages slower than the server is sending them.
|
||||
Note that this could lead the queue to grow without bound, eventually
|
||||
crashing the server. For this reason, we're only allowing pacemaker
|
||||
daemons to ignore the queue size limit.
|
||||
|
||||
Potential problems with this approach:
|
||||
|
||||
* If the client is so busy that it can't receive even a single message
|
||||
that crm_ipcs_flush_events tries to send, it will still be evicted.
|
||||
However, the flush operation does retry with a delay several times
|
||||
giving the client time to finish up what it's doing.
|
||||
|
||||
* We have timers all over the place with daemons waiting on replies.
|
||||
It's possible that because we are no longer just evicting the clients,
|
||||
we will now see those timers expire which will just lead to different
|
||||
problems. If so, these fixes would probably need to take place in the
|
||||
client code.
|
||||
|
||||
Fixes T38
|
||||
---
|
||||
lib/common/ipc_server.c | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/common/ipc_server.c b/lib/common/ipc_server.c
|
||||
index c305dfc..16a2986 100644
|
||||
--- a/lib/common/ipc_server.c
|
||||
+++ b/lib/common/ipc_server.c
|
||||
@@ -551,10 +551,20 @@ crm_ipcs_flush_events(pcmk__client_t *c)
|
||||
* consume resources indefinitely.
|
||||
*/
|
||||
if (queue_len > QB_MAX(c->queue_max, PCMK_IPC_DEFAULT_QUEUE_MAX)) {
|
||||
- if ((c->queue_backlog <= 1) || (queue_len < c->queue_backlog)) {
|
||||
- /* Don't evict for a new or shrinking backlog */
|
||||
+ /* Don't evict:
|
||||
+ * - Clients with a new backlog.
|
||||
+ * - Clients with a shrinking backlog (the client is processing
|
||||
+ * messages faster than the server is sending them).
|
||||
+ * - Clients that are pacemaker daemons and have had any messages sent
|
||||
+ * to them in this flush call (the server is sending messages faster
|
||||
+ * than the client is processing them, but the client is not dead).
|
||||
+ */
|
||||
+ if ((c->queue_backlog <= 1)
|
||||
+ || (queue_len < c->queue_backlog)
|
||||
+ || ((sent > 0) && crm_is_daemon_name(c->name))) {
|
||||
crm_warn("Client with process ID %u has a backlog of %u messages "
|
||||
CRM_XS " %p", c->pid, queue_len, c->ipcs);
|
||||
+
|
||||
} else {
|
||||
crm_err("Evicting client with process ID %u due to backlog of %u messages "
|
||||
CRM_XS " %p", c->pid, queue_len, c->ipcs);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
From 6b5e50b272c26c95e9fae1c3270c77a8d72446e8 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Tue, 30 Sep 2025 13:50:53 -0400
|
||||
Subject: [PATCH 5/5] Feature: libcrmcommon: Update documentation for
|
||||
cluster-ipc-limit.
|
||||
|
||||
Clarify that this no longer applies to pacemaker daemons.
|
||||
---
|
||||
cts/cli/regression.daemons.exp | 4 ++--
|
||||
doc/sphinx/Pacemaker_Explained/cluster-options.rst | 12 +++++++-----
|
||||
lib/common/options.c | 6 +++---
|
||||
3 files changed, 12 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/cts/cli/regression.daemons.exp b/cts/cli/regression.daemons.exp
|
||||
index 678cb62..dffbe6a 100644
|
||||
--- a/cts/cli/regression.daemons.exp
|
||||
+++ b/cts/cli/regression.daemons.exp
|
||||
@@ -11,8 +11,8 @@
|
||||
<content type="boolean" default=""/>
|
||||
</parameter>
|
||||
<parameter name="cluster-ipc-limit">
|
||||
- <longdesc lang="en">Raise this if log has "Evicting client" messages for cluster daemon PIDs (a good value is the number of resources in the cluster multiplied by the number of nodes).</longdesc>
|
||||
- <shortdesc lang="en">Maximum IPC message backlog before disconnecting a cluster daemon</shortdesc>
|
||||
+ <longdesc lang="en">Raise this if log has "Evicting client" messages for cluster PIDs (a good value is the number of resources in the cluster multiplied by the number of nodes).</longdesc>
|
||||
+ <shortdesc lang="en">Maximum IPC message backlog before disconnecting a client</shortdesc>
|
||||
<content type="integer" default=""/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
diff --git a/doc/sphinx/Pacemaker_Explained/cluster-options.rst b/doc/sphinx/Pacemaker_Explained/cluster-options.rst
|
||||
index 77bd7e6..fe2d4f1 100644
|
||||
--- a/doc/sphinx/Pacemaker_Explained/cluster-options.rst
|
||||
+++ b/doc/sphinx/Pacemaker_Explained/cluster-options.rst
|
||||
@@ -675,11 +675,13 @@ values, by running the ``man pacemaker-schedulerd`` and
|
||||
cluster-ipc-limit
|
||||
- :ref:`nonnegative integer <nonnegative_integer>`
|
||||
- 500
|
||||
- - The maximum IPC message backlog before one cluster daemon will
|
||||
- disconnect another. This is of use in large clusters, for which a good
|
||||
- value is the number of resources in the cluster multiplied by the number
|
||||
- of nodes. The default of 500 is also the minimum. Raise this if you see
|
||||
- "Evicting client" log messages for cluster daemon process IDs.
|
||||
+ - The maximum IPC message backlog before a cluster daemon will disconnect
|
||||
+ a client. Other cluster daemons are not subject to this limit as long as
|
||||
+ they are still processing messages. This is of use in large clusters,
|
||||
+ for which a good value is the number of resources in the cluster
|
||||
+ multiplied by the number of nodes. The default of 500 is also the
|
||||
+ minimum. Raise this if you see "Evicting client" log messages for
|
||||
+ cluster process IDs.
|
||||
* - .. _pe_error_series_max:
|
||||
|
||||
.. index::
|
||||
diff --git a/lib/common/options.c b/lib/common/options.c
|
||||
index 96f059c..d3fc684 100644
|
||||
--- a/lib/common/options.c
|
||||
+++ b/lib/common/options.c
|
||||
@@ -422,10 +422,10 @@ static pcmk__cluster_option_t cluster_options[] = {
|
||||
"cluster-ipc-limit", NULL, "integer", NULL,
|
||||
"500", pcmk__valid_positive_number,
|
||||
pcmk__opt_context_based,
|
||||
- N_("Maximum IPC message backlog before disconnecting a cluster daemon"),
|
||||
+ N_("Maximum IPC message backlog before disconnecting a client"),
|
||||
N_("Raise this if log has \"Evicting client\" messages for cluster "
|
||||
- "daemon PIDs (a good value is the number of resources in the "
|
||||
- "cluster multiplied by the number of nodes)."),
|
||||
+ "PIDs (a good value is the number of resources in the cluster "
|
||||
+ "multiplied by the number of nodes)."),
|
||||
},
|
||||
|
||||
// Orphans and stopping
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@ -1,88 +0,0 @@
|
||||
From 7be9cdca98217d002497714aaafcfc292c02555b Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Fri, 31 Oct 2025 11:24:14 -0400
|
||||
Subject: [PATCH] Med: daemons: Don't add repeated I_PE_CALC messages to the
|
||||
fsa queue.
|
||||
|
||||
Let's say you have a two node cluster, node1 and node2. For purposes of
|
||||
testing, it's easiest if you use fence_dummy instead of a real fencing
|
||||
agent as this will fake fencing happen but without rebooting the node so
|
||||
you can see all the log files.
|
||||
|
||||
Assume the DC is node1. Now do the following:
|
||||
|
||||
- pcs node standby node1
|
||||
- pcs resource defaults update resource-stickiness=1
|
||||
- for i in $(seq 1 300); do echo $i; pcs resource create dummy$i ocf:heartbeat:Dummy --group dummy-group; done
|
||||
- pcs node unstandby node1
|
||||
|
||||
It will take a long time to create that many resources. After node1
|
||||
comes out of standby, it'll take a minute or two but eventually you'll
|
||||
see that node1 was fenced. On node1, you'll see a lot of transition
|
||||
abort messages happen. Each of these transition aborts causes an
|
||||
I_PE_CALC message to be generated and added to the fsa queue. In my
|
||||
testing, I've seen the queue grow to ~ 600 messages, all of which are
|
||||
exactly the same thing.
|
||||
|
||||
The FSA is triggered at G_PRIORITY_HIGH, and once it is triggered, it
|
||||
will run until its queue is empty. With so many messages being added so
|
||||
quickly, we've basically ensured it won't be empty any time soon. While
|
||||
controld is processing the FSA messages, it will be unable to read
|
||||
anything out of the IPC backlog.
|
||||
|
||||
based continues to attempt to send IPC events to controld but is unable
|
||||
to do so, so the backlog continues to grow. Eventually, the backlog
|
||||
reaches that 500 message threshold without anything having been read by
|
||||
controld, which triggers the eviction process.
|
||||
|
||||
There doesn't seem to be any reason for all these I_PE_CALC messages to
|
||||
be generated. They're all exactly the same, and they don't appear to be
|
||||
tagged with any unique data tying them to a specific query, and their
|
||||
presence just slows everything down.
|
||||
|
||||
Thus, the fix here is very simple: if the latest message in the queue is
|
||||
an I_PE_CALC message, just don't add another one. We could also make
|
||||
sure there's only ever one I_PE_CALC message in the queue, but there
|
||||
could potentially be valid reasons for there to be multiple interleaved
|
||||
with other message types. I am erring on the side of caution with this
|
||||
minimal fix.
|
||||
|
||||
Related: RHEL-76276
|
||||
---
|
||||
daemons/controld/controld_messages.c | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/daemons/controld/controld_messages.c b/daemons/controld/controld_messages.c
|
||||
index 0b0f25b..30af707 100644
|
||||
--- a/daemons/controld/controld_messages.c
|
||||
+++ b/daemons/controld/controld_messages.c
|
||||
@@ -73,6 +73,26 @@ register_fsa_input_adv(enum crmd_fsa_cause cause, enum crmd_fsa_input input,
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (input == I_PE_CALC) {
|
||||
+ GList *ele = NULL;
|
||||
+
|
||||
+ if (prepend) {
|
||||
+ ele = g_list_first(controld_globals.fsa_message_queue);
|
||||
+ } else {
|
||||
+ ele = g_list_last(controld_globals.fsa_message_queue);
|
||||
+ }
|
||||
+
|
||||
+ if (ele != NULL) {
|
||||
+ fsa_data_t *message = (fsa_data_t *) ele->data;
|
||||
+
|
||||
+ if (message->fsa_input == I_PE_CALC) {
|
||||
+ crm_debug("%s item in fsa queue is I_PE_CALC, not adding another",
|
||||
+ (prepend ? "First" : "Last"));
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (input == I_WAIT_FOR_EVENT) {
|
||||
controld_set_global_flags(controld_fsa_is_stalled);
|
||||
crm_debug("Stalling the FSA pending further input: source=%s cause=%s data=%p queue=%d",
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@ -1,386 +0,0 @@
|
||||
From 2d9c031078a83796dcbe4faa0bad3579c4fcd1c3 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 14 May 2026 12:57:17 -0400
|
||||
Subject: [PATCH 1/5] Med: libcrmcommon: Add sanity checks to
|
||||
localized_remote_header.
|
||||
|
||||
These checks are present in the main and 3.0 branches, and they make
|
||||
sense here as well.
|
||||
---
|
||||
lib/common/remote.c | 52 ++++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 47 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/common/remote.c b/lib/common/remote.c
|
||||
index fe19296..f771f46 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2008-2023 the Pacemaker project contributors
|
||||
+ * Copyright 2008-2026 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
-#include <inttypes.h> // PRIx32
|
||||
+#include <inttypes.h> // PRIu32, PRIx32
|
||||
|
||||
#include <glib.h>
|
||||
#include <bzlib.h>
|
||||
@@ -97,11 +97,18 @@ struct remote_header_v0 {
|
||||
static struct remote_header_v0 *
|
||||
localized_remote_header(pcmk__remote_t *remote)
|
||||
{
|
||||
- struct remote_header_v0 *header = (struct remote_header_v0 *)remote->buffer;
|
||||
- if(remote->buffer_offset < sizeof(struct remote_header_v0)) {
|
||||
+ struct remote_header_v0 *header = NULL;
|
||||
+ size_t expected_size = 0;
|
||||
+
|
||||
+ if ((remote == NULL) || (remote->buffer == NULL)
|
||||
+ || (remote->buffer_offset < sizeof(struct remote_header_v0))) {
|
||||
+
|
||||
+ // Caller error or we haven't received the full header yet
|
||||
return NULL;
|
||||
+ }
|
||||
|
||||
- } else if(header->endian != ENDIAN_LOCAL) {
|
||||
+ header = (struct remote_header_v0 *) remote->buffer;
|
||||
+ if (header->endian != ENDIAN_LOCAL) {
|
||||
uint32_t endian = __swab32(header->endian);
|
||||
|
||||
CRM_LOG_ASSERT(endian == ENDIAN_LOCAL);
|
||||
@@ -123,6 +130,41 @@ localized_remote_header(pcmk__remote_t *remote)
|
||||
header->payload_uncompressed = __swab32(header->payload_uncompressed);
|
||||
}
|
||||
|
||||
+ // Sanity checks
|
||||
+ if (header->payload_offset != sizeof(struct remote_header_v0)) {
|
||||
+ crm_err("Header payload offset %" PRIu32 " does not have expected "
|
||||
+ "size %zu", header->payload_offset,
|
||||
+ sizeof(struct remote_header_v0));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (header->payload_compressed != 0) {
|
||||
+ if (header->payload_compressed > (SIZE_MAX - header->payload_offset)) {
|
||||
+ crm_err("Header compressed size %" PRIu32 " is too large",
|
||||
+ header->payload_compressed);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ expected_size = (size_t) header->payload_offset
|
||||
+ + header->payload_compressed;
|
||||
+
|
||||
+ } else {
|
||||
+ if (header->payload_uncompressed > (SIZE_MAX - header->payload_offset)) {
|
||||
+ crm_err("Header uncompressed size %" PRIu32 " is too large",
|
||||
+ header->payload_uncompressed);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ expected_size = (size_t) header->payload_offset
|
||||
+ + header->payload_uncompressed;
|
||||
+ }
|
||||
+
|
||||
+ if (expected_size != header->size_total) {
|
||||
+ crm_err("Header total size %" PRIu32 " does not match calculated "
|
||||
+ "size %zu", header->size_total, expected_size);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
return header;
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
From 43cadbc4ce424a881ec0b3258d65e4f94bda3175 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 14 May 2026 13:06:57 -0400
|
||||
Subject: [PATCH 2/5] High: libcrmcommon: Fix integer overflow in remote
|
||||
message code.
|
||||
|
||||
It's possible for a client to send a specifically constructed header
|
||||
packet that will cause our size checks in pcmk__remote_message_xml to
|
||||
overflow, which could result in crashes (potentially leading to a node
|
||||
being fenced) or memory corruption problems.
|
||||
|
||||
Such a header would have to indicate that the payload is compressed,
|
||||
which nothing in pacemaker is doing. In fact, we haven't used any of
|
||||
the remote message compression code since it was introduced in 2013
|
||||
which explains why we haven't seen any problems with it. Thus, it would
|
||||
require a malicious client to cause this to happen.
|
||||
|
||||
It would also require remote CIB administration to be enabled via
|
||||
remote-clear-port or remote-tls-port, which we do not do by default.
|
||||
Additionally, if remote-tls-port is in use, it requires the client to
|
||||
complete the gnutls handshake procedure (pcmk__remote_message_xml is
|
||||
only called in cib_remote_msg after the handshake but before the client
|
||||
has authenticated).
|
||||
|
||||
Co-Authored-By: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
lib/common/remote.c | 50 +++++++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 44 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/lib/common/remote.c b/lib/common/remote.c
|
||||
index f771f46..54620c2 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -593,15 +593,53 @@ pcmk__remote_message_xml(pcmk__remote_t *remote)
|
||||
}
|
||||
|
||||
/* Support compression on the receiving end now, in case we ever want to add it later */
|
||||
- if (header->payload_compressed) {
|
||||
+ if (header->payload_compressed != 0) {
|
||||
int rc = 0;
|
||||
- unsigned int size_u = 1 + header->payload_uncompressed;
|
||||
- char *uncompressed = calloc(1, header->payload_offset + size_u);
|
||||
+ unsigned int size_u = 0;
|
||||
+ char *uncompressed = NULL;
|
||||
+
|
||||
+#if (UINT32_MAX < UINT_MAX)
|
||||
+ if (header->payload_uncompressed >= UINT_MAX) {
|
||||
+ crm_err("Couldn't decompress message because uncompressed "
|
||||
+ "payload size (%" PRIu32 ") is greater than UINT_MAX "
|
||||
+ "(%u)", header->payload_uncompressed, UINT_MAX);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
- crm_trace("Decompressing message data %d bytes into %d bytes",
|
||||
- header->payload_compressed, size_u);
|
||||
+ /* @TODO Is the extra byte for the null terminator?
|
||||
+ * pcmk__remote_send_xml() also adds one byte to the iov length.
|
||||
+ * (However, we do need to account for the possibility of receiving a
|
||||
+ * message from an untrusted sender.)
|
||||
+ */
|
||||
+ size_u = 1 + header->payload_uncompressed;
|
||||
+
|
||||
+ /* Header and uncompressed payload must fit in the destination buffer.
|
||||
+ * We do not need to separately check the header size here since
|
||||
+ * localized_remote_header will return NULL if it's incorrect.
|
||||
+ */
|
||||
+#if (UINT_MAX >= SIZE_MAX)
|
||||
+ if ((size_u >= SIZE_MAX)
|
||||
+ || (header->payload_offset > (SIZE_MAX - size_u))) {
|
||||
+#else
|
||||
+ if (header->payload_offset > (SIZE_MAX - size_u)) {
|
||||
+#endif
|
||||
+ crm_err("Couldn't decompress message because the required buffer "
|
||||
+ "size (%" PRIu32 " + %u) is greater than SIZE_MAX (%zu)",
|
||||
+ header->payload_offset, size_u, SIZE_MAX);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ crm_trace("Decompressing message data %" PRIu32 " bytes into %u "
|
||||
+ "bytes", header->payload_compressed, size_u);
|
||||
+
|
||||
+ uncompressed = calloc(1, header->payload_offset + size_u);
|
||||
+ if (uncompressed == NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
- rc = BZ2_bzBuffToBuffDecompress(uncompressed + header->payload_offset, &size_u,
|
||||
+ rc = BZ2_bzBuffToBuffDecompress(uncompressed + header->payload_offset,
|
||||
+ &size_u,
|
||||
remote->buffer + header->payload_offset,
|
||||
header->payload_compressed, 1, 0);
|
||||
rc = pcmk__bzlib2rc(rc);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
From 07f44f9db114ea7f609029410712835c1256cd55 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 14 May 2026 13:26:07 -0400
|
||||
Subject: [PATCH 3/5] High: libcrmcommon: Limit the max size of a remote
|
||||
message.
|
||||
|
||||
Previously, we were just taking the sizes straight from the message
|
||||
header and allocating however much memory was asked for without
|
||||
checking. It's possible for a malicious client to ask for a very large
|
||||
amount of memory (say, 4 GB since that'll fit in the uint32_t value for
|
||||
header->size_total).
|
||||
|
||||
In that case, due to the use of calloc, we'll crash due to an out of
|
||||
memory error and the node could potentially be fenced.
|
||||
|
||||
The fix is to simply check that the client isn't asking for too much
|
||||
memory. This does unfortunately impose a size restriction on the
|
||||
message. It's doubly unfortunate given how much work we've recently put
|
||||
into removing restrictions on IPC messages allowing for much larger
|
||||
clusters.
|
||||
|
||||
I think the biggest thing these messages will ever contain is a CIB, so
|
||||
for now I'm going with a limit of 20 MB. It is not my intention that
|
||||
this become a tuneable parameter that is exposed to the user.
|
||||
---
|
||||
include/crm/common/remote_internal.h | 5 ++++-
|
||||
lib/common/remote.c | 16 +++++++++++++++-
|
||||
2 files changed, 19 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/remote_internal.h b/include/crm/common/remote_internal.h
|
||||
index 030c7a4..c39fcef 100644
|
||||
--- a/include/crm/common/remote_internal.h
|
||||
+++ b/include/crm/common/remote_internal.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2008-2023 the Pacemaker project contributors
|
||||
+ * Copyright 2008-2026 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -10,6 +10,9 @@
|
||||
#ifndef PCMK__REMOTE_INTERNAL__H
|
||||
# define PCMK__REMOTE_INTERNAL__H
|
||||
|
||||
+// The maximum payload size for a remote message (in bytes)
|
||||
+#define PCMK__REMOTE_MSG_MAX_SIZE (20 * 1024 * 1024)
|
||||
+
|
||||
// internal functions from remote.c
|
||||
|
||||
typedef struct pcmk__remote_s pcmk__remote_t;
|
||||
diff --git a/lib/common/remote.c b/lib/common/remote.c
|
||||
index 54620c2..256ff11 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -597,6 +597,7 @@ pcmk__remote_message_xml(pcmk__remote_t *remote)
|
||||
int rc = 0;
|
||||
unsigned int size_u = 0;
|
||||
char *uncompressed = NULL;
|
||||
+ size_t buffer_size = 0;
|
||||
|
||||
#if (UINT32_MAX < UINT_MAX)
|
||||
if (header->payload_uncompressed >= UINT_MAX) {
|
||||
@@ -630,10 +631,17 @@ pcmk__remote_message_xml(pcmk__remote_t *remote)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ buffer_size = (size_t) header->payload_offset + size_u;
|
||||
+ if (buffer_size > PCMK__REMOTE_MSG_MAX_SIZE) {
|
||||
+ crm_err("Message size %zu is larger than max allowed %u bytes",
|
||||
+ buffer_size, PCMK__REMOTE_MSG_MAX_SIZE);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
crm_trace("Decompressing message data %" PRIu32 " bytes into %u "
|
||||
"bytes", header->payload_compressed, size_u);
|
||||
|
||||
- uncompressed = calloc(1, header->payload_offset + size_u);
|
||||
+ uncompressed = calloc(1, buffer_size);
|
||||
if (uncompressed == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -780,6 +788,12 @@ read_available_remote_data(pcmk__remote_t *remote)
|
||||
read_len = header->size_total;
|
||||
}
|
||||
|
||||
+ if (read_len > PCMK__REMOTE_MSG_MAX_SIZE) {
|
||||
+ crm_err("Message size %zu is larger than max allowed %u bytes",
|
||||
+ read_len, PCMK__REMOTE_MSG_MAX_SIZE);
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+
|
||||
/* automatically grow the buffer when needed */
|
||||
if(remote->buffer_size < read_len) {
|
||||
remote->buffer_size = 2 * read_len;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
From 3d9bf582dc28b94d59037ac32a3b4ee6498a3e35 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Fri, 15 May 2026 10:19:33 -0400
|
||||
Subject: [PATCH 4/5] High: libcrmcommon: Fix an integer overflow in
|
||||
pcmk__remote_send_xml.
|
||||
|
||||
iov[0].iov_len is a size_t. iov[1].iov_len is also a size_t (which
|
||||
comes from the length of a string, which is a size_t). We're adding
|
||||
those together and storing them in a uint32_t, so make sure the result
|
||||
will fit.
|
||||
|
||||
Fixes RHEL-181155
|
||||
---
|
||||
lib/common/remote.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/lib/common/remote.c b/lib/common/remote.c
|
||||
index 256ff11..26f1917 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -560,6 +560,13 @@ pcmk__remote_send_xml(pcmk__remote_t *remote, const xmlNode *msg)
|
||||
header->version = REMOTE_MSG_VERSION;
|
||||
header->payload_offset = iov[0].iov_len;
|
||||
header->payload_uncompressed = iov[1].iov_len;
|
||||
+
|
||||
+ if ((UINT32_MAX - iov[0].iov_len) < iov[1].iov_len) {
|
||||
+ crm_err("Remote message size %zu + %zu exceeds maximum of %" PRIu32,
|
||||
+ iov[0].iov_len, iov[1].iov_len, UINT32_MAX);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
header->size_total = iov[0].iov_len + iov[1].iov_len;
|
||||
|
||||
rc = remote_send_iovs(remote, iov, 2);
|
||||
@@ -568,6 +575,7 @@ pcmk__remote_send_xml(pcmk__remote_t *remote, const xmlNode *msg)
|
||||
pcmk_rc_str(rc), rc);
|
||||
}
|
||||
|
||||
+done:
|
||||
free(iov[0].iov_base);
|
||||
free(iov[1].iov_base);
|
||||
return rc;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
From d022a58012629a5d4ecc84dc5d2f325f01738adc Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 17 Jun 2026 15:55:28 -0400
|
||||
Subject: [PATCH 5/5] Med: libcrmcommon: Add additional checks to
|
||||
pcmk__remote_message_xml.
|
||||
|
||||
coverity flags the existing code for using a tainted expression as an
|
||||
index to a pointer. While we're fixing other range errors and overflows
|
||||
in this code, we should fix this one as well by porting the existing
|
||||
code from the main branch.
|
||||
---
|
||||
lib/common/remote.c | 14 +++++++++++++-
|
||||
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/common/remote.c b/lib/common/remote.c
|
||||
index 26f1917..fbcf0a0 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -594,6 +594,7 @@ xmlNode *
|
||||
pcmk__remote_message_xml(pcmk__remote_t *remote)
|
||||
{
|
||||
xmlNode *xml = NULL;
|
||||
+ size_t data_size = 0;
|
||||
struct remote_header_v0 *header = localized_remote_header(remote);
|
||||
|
||||
if (header == NULL) {
|
||||
@@ -686,7 +687,18 @@ pcmk__remote_message_xml(pcmk__remote_t *remote)
|
||||
/* take ownership of the buffer */
|
||||
remote->buffer_offset = 0;
|
||||
|
||||
- CRM_LOG_ASSERT(remote->buffer[sizeof(struct remote_header_v0) + header->payload_uncompressed - 1] == 0);
|
||||
+ data_size = (size_t) header->payload_offset + header->payload_uncompressed;
|
||||
+
|
||||
+ // Ensure the buffer is as big as it should be
|
||||
+ CRM_CHECK(remote->buffer_size >= data_size, return NULL);
|
||||
+
|
||||
+ /* Ensure the buffer is null-terminated (see
|
||||
+ * pcmk__read_available_remote_data()).
|
||||
+ *
|
||||
+ * Note that payload_uncompressed contains the payload size including the
|
||||
+ * null byte (see pcmk__remote_send_xml()).
|
||||
+ */
|
||||
+ CRM_CHECK(remote->buffer[data_size] == '\0', return NULL);
|
||||
|
||||
xml = string2xml(remote->buffer + header->payload_offset);
|
||||
if (xml == NULL && header->version > REMOTE_MSG_VERSION) {
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
## can be incremented to build packages reliably considered "newer"
|
||||
## than previously built packages with the same pcmkversion)
|
||||
%global pcmkversion 2.1.7
|
||||
%global specversion 5
|
||||
%global specversion 4
|
||||
|
||||
## Upstream commit (full commit ID, abbreviated commit ID, or tag) to build
|
||||
%global commit 0f7f88312f7a1ccedee60bf768aba79ee13d41e0
|
||||
@ -244,7 +244,7 @@
|
||||
Name: pacemaker
|
||||
Summary: Scalable High-Availability cluster resource manager
|
||||
Version: %{pcmkversion}
|
||||
Release: %{pcmk_release}.6%{?dist}
|
||||
Release: %{pcmk_release}%{?dist}
|
||||
%if %{defined _unitdir}
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-or-later
|
||||
%else
|
||||
@ -275,13 +275,6 @@ Patch007: 007-option-metadata.patch
|
||||
Patch008: 008-attrd-prep.patch
|
||||
Patch009: 009-attrd-cache-3.patch
|
||||
Patch010: 010-crm_attribute-free.patch
|
||||
Patch011: 011-attrd-memory-leak.patch
|
||||
Patch012: 012-dont-set-as-xml-id.patch
|
||||
Patch013: 013-crm_node-i-initialize.patch
|
||||
Patch014: 014-remote-fencing.patch
|
||||
Patch015: 015-ipc-disconnect.patch
|
||||
Patch016: 016-fewer-messages.patch
|
||||
Patch017: 017-remote-overflow.patch
|
||||
|
||||
Requires: resource-agents
|
||||
Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release}
|
||||
@ -592,12 +585,6 @@ export LDFLAGS_HARDENED_EXE="%{?_hardening_ldflags}"
|
||||
export LDFLAGS_HARDENED_LIB="%{?_hardening_ldflags}"
|
||||
%endif
|
||||
|
||||
# DO NOT REMOVE THE FOLLOWING LINE!
|
||||
# This is necessary to ensure we use the git commit ID from the
|
||||
# pacemaker-abcd1234 directory name as the latest commit ID when
|
||||
# generating crm_config.h.
|
||||
rm -rf .git
|
||||
|
||||
./autogen.sh
|
||||
|
||||
%{configure} \
|
||||
@ -1033,34 +1020,6 @@ exit 0
|
||||
%license %{nagios_name}-%{nagios_hash}/COPYING
|
||||
|
||||
%changelog
|
||||
* Tue Jun 30 2026 Chris Lumens <clumens@redhat.com> - 2.1.7-5.6
|
||||
- Fix integer overflows in remote message decompression code (CVE-2026-10649)
|
||||
- Resolves: RHEL-181157
|
||||
|
||||
* Mon Nov 17 2025 Chris Lumens <clumens@redhat.com> - 2.1.7-5.5
|
||||
- Don't overwhelm the FSA queue with repeated CIB queries
|
||||
- Related: RHEL-76276
|
||||
|
||||
* Tue Sep 30 2025 Chris Lumens <clumens@redhat.com> - 2.1.7-5.4
|
||||
- Be more lenient in evicting IPC clients
|
||||
- Resolves: RHEL-76276
|
||||
|
||||
* Thu Jul 10 2025 Chris Lumens <clumens@redhat.com> - 2.1.7-5.3
|
||||
- Add option for controlling remote node fencing behavior
|
||||
- Resolves: RHEL-93220
|
||||
|
||||
* Wed Jul 24 2024 Chris Lumens <clumens@redhat.com> - 2.1.7-5.2
|
||||
- Fix an error in node ID handling in `crm_node -i`
|
||||
- Resolves: RHEL-49928
|
||||
|
||||
* Fri Jun 7 2024 Chris Lumens <clumens@redhat.com> - 2.1.7-5.1
|
||||
- Fix a memory leak in the attribute daemon
|
||||
- Resolves: RHEL-40145
|
||||
|
||||
* Thu Mar 21 2024 Chris Lumens <clumens@redhat.com> - 2.1.7-5
|
||||
- Fix upgrading to this package on multilib systems
|
||||
- Resolves: RHEL-29007
|
||||
|
||||
* Thu Feb 1 2024 Chris Lumens <clumens@redhat.com> - 2.1.7-4
|
||||
- Properly validate attribute set type in pacemaker-attrd
|
||||
- Fix `crm_attribute -t nodes --node localhost`
|
||||
|
||||
Loading…
Reference in New Issue
Block a user