import Oracle_OSS pacemaker-2.1.10-3.0.1.el9_8
This commit is contained in:
parent
48b3808443
commit
bd9348bff9
131
SOURCES/001-crm_resource_wait.patch
Normal file
131
SOURCES/001-crm_resource_wait.patch
Normal file
@ -0,0 +1,131 @@
|
||||
From 17a2d7acffc86e06b2fa8b49c96c33d72466e7f7 Mon Sep 17 00:00:00 2001
|
||||
From: Reid Wahl <nrwahl@protonmail.com>
|
||||
Date: Fri, 5 Sep 2025 20:35:31 -0700
|
||||
Subject: [PATCH] Fix: tools: Handle large timeouts correctly in crm_resource
|
||||
--wait
|
||||
|
||||
Previously, if the --timeout value parsed to a value greater than
|
||||
(UINT_MAX - 999), the wait timeout would overflow. The effective timeout
|
||||
would be either 0 seconds or 1 second. This is because 999 was added to
|
||||
the guint value before passing it to pcmk__timeout_ms2s().
|
||||
|
||||
Now, we simply pass the timeout in milliseconds to
|
||||
pcmk__timeout_ms2s(), without adding 999.
|
||||
|
||||
This implies a slight behavior change. Previously, timeouts were always
|
||||
rounded up to the next greatest second. Now, they're rounded to the
|
||||
nearest second. For example, previously:
|
||||
* timeout values between 1ms and 500ms => wait timeout of 1 second
|
||||
* timeout values between 501ms and 1500ms => wait timeout of 2 seconds
|
||||
* timeout values between 1501ms and 2500ms => wait timeout of 3 seconds
|
||||
* and so on
|
||||
|
||||
Now:
|
||||
* timeout values between 1ms and 1499ms => wait timeout of 1 second
|
||||
* timeout values between 1500ms and 2499ms => wait timeout of 2 seconds
|
||||
* timeout values between 2500ms and 3499ms => wait timeout of 3 seconds
|
||||
* and so on
|
||||
|
||||
The previous rounding behavior has existed since crm_resource --wait was
|
||||
added by 424afcdf.
|
||||
|
||||
Update the help text to note the granularity and rounding behavior. The
|
||||
exact behavior of the restart command is confusing, and its logic should
|
||||
be cleaned up in the future.
|
||||
|
||||
Fixes RHEL-45869
|
||||
Fixes RHEL-86148
|
||||
Closes T841
|
||||
|
||||
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
|
||||
---
|
||||
include/crm/common/internal.h | 1 +
|
||||
lib/common/utils.c | 30 ++++++++++++++++++++++++++++++
|
||||
tools/crm_resource.c | 4 +++-
|
||||
tools/crm_resource_runtime.c | 2 +-
|
||||
4 files changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/internal.h b/include/crm/common/internal.h
|
||||
index 7d1e95f..ee26321 100644
|
||||
--- a/include/crm/common/internal.h
|
||||
+++ b/include/crm/common/internal.h
|
||||
@@ -249,6 +249,7 @@ void pcmk__daemonize(const char *name, const char *pidfile);
|
||||
void pcmk__panic(const char *origin);
|
||||
pid_t pcmk__locate_sbd(void);
|
||||
void pcmk__sleep_ms(unsigned int ms);
|
||||
+guint pcmk__timeout_ms2s(guint timeout_ms);
|
||||
|
||||
extern int pcmk__score_red;
|
||||
extern int pcmk__score_green;
|
||||
diff --git a/lib/common/utils.c b/lib/common/utils.c
|
||||
index 9e44c22..0a38811 100644
|
||||
--- a/lib/common/utils.c
|
||||
+++ b/lib/common/utils.c
|
||||
@@ -413,6 +413,36 @@ pcmk__sleep_ms(unsigned int ms)
|
||||
#endif
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ * \internal
|
||||
+ * \brief Convert milliseconds to seconds
|
||||
+ *
|
||||
+ * \param[in] timeout_ms The interval, in ms
|
||||
+ *
|
||||
+ * \return If \p timeout_ms is 0, return 0. Otherwise, return the number of
|
||||
+ * seconds, rounded to the nearest integer, with a minimum of 1.
|
||||
+ */
|
||||
+guint
|
||||
+pcmk__timeout_ms2s(guint timeout_ms)
|
||||
+{
|
||||
+ guint quot, rem;
|
||||
+
|
||||
+ if (timeout_ms == 0) {
|
||||
+ return 0;
|
||||
+ } else if (timeout_ms < 1000) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ quot = timeout_ms / 1000;
|
||||
+ rem = timeout_ms % 1000;
|
||||
+
|
||||
+ if (rem >= 500) {
|
||||
+ quot += 1;
|
||||
+ }
|
||||
+
|
||||
+ return quot;
|
||||
+}
|
||||
+
|
||||
// Deprecated functions kept only for backward API compatibility
|
||||
// LCOV_EXCL_START
|
||||
|
||||
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
|
||||
index 898c21e..ac50c5e 100644
|
||||
--- a/tools/crm_resource.c
|
||||
+++ b/tools/crm_resource.c
|
||||
@@ -766,7 +766,9 @@ static GOptionEntry addl_entries[] = {
|
||||
"ID" },
|
||||
{ "timeout", 'T', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, timeout_cb,
|
||||
"(Advanced) Abort if command does not finish in this time (with\n"
|
||||
- INDENT "--restart, --wait, --force-*)",
|
||||
+ INDENT "--restart, --wait, --force-*). The --restart command uses a\n"
|
||||
+ INDENT "two-second granularity and the --wait command uses a one-second\n"
|
||||
+ INDENT "granularity, with rounding.",
|
||||
"N" },
|
||||
{ "all", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.all,
|
||||
"List all options, including advanced and deprecated (with\n"
|
||||
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
|
||||
index 7350f07..286c10c 100644
|
||||
--- a/tools/crm_resource_runtime.c
|
||||
+++ b/tools/crm_resource_runtime.c
|
||||
@@ -1977,7 +1977,7 @@ wait_till_stable(pcmk__output_t *out, guint timeout_ms, cib_t * cib)
|
||||
if (timeout_ms == 0) {
|
||||
expire_time += WAIT_DEFAULT_TIMEOUT_S;
|
||||
} else {
|
||||
- expire_time += (timeout_ms + 999) / 1000;
|
||||
+ expire_time += pcmk__timeout_ms2s(timeout_ms);
|
||||
}
|
||||
|
||||
scheduler = pe_new_working_set();
|
||||
--
|
||||
2.47.1
|
||||
|
||||
178
SOURCES/002-ipc_connect_retry.patch
Normal file
178
SOURCES/002-ipc_connect_retry.patch
Normal file
@ -0,0 +1,178 @@
|
||||
From 8ff58d786907b64c32350e72e341cdd0f5026813 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Jones <thomas.jones@ibm.com>
|
||||
Date: Fri, 30 May 2025 16:40:13 -0400
|
||||
Subject: [PATCH 1/2] Fix: libcrmcommon: Add retries on connect to avoid fatal
|
||||
errors when sub-daemons communicate Add pcmk__connect_ipc_retry_conrefused()
|
||||
and use it where it makes sense Add retry loop to
|
||||
connect_and_send_attrd_request() that retries connect and send.
|
||||
|
||||
---
|
||||
daemons/controld/controld_schedulerd.c | 2 +-
|
||||
include/crm/common/ipc_internal.h | 4 ++++
|
||||
lib/common/ipc_attrd.c | 19 ++++++++++++----
|
||||
lib/common/ipc_client.c | 30 ++++++++++++++++++++++++++
|
||||
lib/pacemaker/pcmk_cluster_queries.c | 2 +-
|
||||
5 files changed, 51 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/daemons/controld/controld_schedulerd.c b/daemons/controld/controld_schedulerd.c
|
||||
index 22b37b8..444bdef 100644
|
||||
--- a/daemons/controld/controld_schedulerd.c
|
||||
+++ b/daemons/controld/controld_schedulerd.c
|
||||
@@ -197,7 +197,7 @@ new_schedulerd_ipc_connection(void)
|
||||
|
||||
pcmk_register_ipc_callback(schedulerd_api, scheduler_event_callback, NULL);
|
||||
|
||||
- rc = pcmk__connect_ipc(schedulerd_api, pcmk_ipc_dispatch_main, 3);
|
||||
+ rc = pcmk__connect_ipc_retry_conrefused(schedulerd_api, pcmk_ipc_dispatch_main, 3);
|
||||
if (rc != pcmk_rc_ok) {
|
||||
crm_err("Error connecting to %s: %s",
|
||||
pcmk_ipc_name(schedulerd_api, true), pcmk_rc_str(rc));
|
||||
diff --git a/include/crm/common/ipc_internal.h b/include/crm/common/ipc_internal.h
|
||||
index 27b8bfc..09145ba 100644
|
||||
--- a/include/crm/common/ipc_internal.h
|
||||
+++ b/include/crm/common/ipc_internal.h
|
||||
@@ -101,6 +101,10 @@ int pcmk__ipc_fd(crm_ipc_t *ipc, int *fd);
|
||||
int pcmk__connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type,
|
||||
int attempts);
|
||||
|
||||
+int pcmk__connect_ipc_retry_conrefused(pcmk_ipc_api_t *api,
|
||||
+ enum pcmk_ipc_dispatch dispatch_type,
|
||||
+ int attempts);
|
||||
+
|
||||
/*
|
||||
* Server-related
|
||||
*/
|
||||
diff --git a/lib/common/ipc_attrd.c b/lib/common/ipc_attrd.c
|
||||
index 5ab0f2d..60a92a0 100644
|
||||
--- a/lib/common/ipc_attrd.c
|
||||
+++ b/lib/common/ipc_attrd.c
|
||||
@@ -152,6 +152,8 @@ create_attrd_op(const char *user_name)
|
||||
static int
|
||||
connect_and_send_attrd_request(pcmk_ipc_api_t *api, const xmlNode *request)
|
||||
{
|
||||
+ static const int max_retries = 5;
|
||||
+ int remaining_attempts = max_retries;
|
||||
int rc = pcmk_rc_ok;
|
||||
bool created_api = false;
|
||||
|
||||
@@ -163,10 +165,19 @@ connect_and_send_attrd_request(pcmk_ipc_api_t *api, const xmlNode *request)
|
||||
created_api = true;
|
||||
}
|
||||
|
||||
- rc = pcmk__connect_ipc(api, pcmk_ipc_dispatch_sync, 5);
|
||||
- if (rc == pcmk_rc_ok) {
|
||||
- rc = pcmk__send_ipc_request(api, request);
|
||||
- }
|
||||
+ // If attrd is killed and is being restarted we will temporarily get
|
||||
+ // ECONNREFUSED on connect if it is already dead or ENOTCONN if it died
|
||||
+ // after we connected to it. We should wait a bit and retry in those cases.
|
||||
+ do {
|
||||
+ if (rc == ENOTCONN || rc == ECONNREFUSED) {
|
||||
+ sleep(max_retries - remaining_attempts);
|
||||
+ }
|
||||
+ rc = pcmk__connect_ipc(api, pcmk_ipc_dispatch_sync, remaining_attempts);
|
||||
+ if (rc == pcmk_rc_ok) {
|
||||
+ rc = pcmk__send_ipc_request(api, request);
|
||||
+ }
|
||||
+ remaining_attempts--;
|
||||
+ } while ((rc == ENOTCONN || rc == ECONNREFUSED) && remaining_attempts >= 0);
|
||||
|
||||
if (created_api) {
|
||||
pcmk_free_ipc_api(api);
|
||||
diff --git a/lib/common/ipc_client.c b/lib/common/ipc_client.c
|
||||
index 24d7745..4ac7810 100644
|
||||
--- a/lib/common/ipc_client.c
|
||||
+++ b/lib/common/ipc_client.c
|
||||
@@ -488,6 +488,36 @@ connect_without_main_loop(pcmk_ipc_api_t *api)
|
||||
return rc;
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ * \internal
|
||||
+ * \brief Connect to a Pacemaker daemon via IPC (retrying after soft errors
|
||||
+ * and ECONNREFUSED)
|
||||
+ *
|
||||
+ * \param[in,out] api IPC API instance
|
||||
+ * \param[in] dispatch_type How IPC replies should be dispatched
|
||||
+ * \param[in] attempts How many times to try (in case of soft error)
|
||||
+ *
|
||||
+ * \return Standard Pacemaker return code
|
||||
+*/
|
||||
+int
|
||||
+pcmk__connect_ipc_retry_conrefused(pcmk_ipc_api_t *api,
|
||||
+ enum pcmk_ipc_dispatch dispatch_type,
|
||||
+ int attempts)
|
||||
+{
|
||||
+ int remaining = attempts;
|
||||
+ int rc = pcmk_rc_ok;
|
||||
+
|
||||
+ do {
|
||||
+ if (rc == ECONNREFUSED) {
|
||||
+ pcmk__sleep_ms((attempts - remaining) * 500);
|
||||
+ }
|
||||
+ rc = pcmk__connect_ipc(api, dispatch_type, remaining);
|
||||
+ remaining--;
|
||||
+ } while (rc == ECONNREFUSED && remaining >= 0);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Connect to a Pacemaker daemon via IPC (retrying after soft errors)
|
||||
diff --git a/lib/pacemaker/pcmk_cluster_queries.c b/lib/pacemaker/pcmk_cluster_queries.c
|
||||
index bbefcda..c1fcf73 100644
|
||||
--- a/lib/pacemaker/pcmk_cluster_queries.c
|
||||
+++ b/lib/pacemaker/pcmk_cluster_queries.c
|
||||
@@ -360,7 +360,7 @@ ipc_connect(data_t *data, enum pcmk_ipc_server server, pcmk_ipc_callback_t cb,
|
||||
pcmk_register_ipc_callback(api, cb, data);
|
||||
}
|
||||
|
||||
- rc = pcmk__connect_ipc(api, dispatch_type, 5);
|
||||
+ rc = pcmk__connect_ipc_retry_conrefused(api, dispatch_type, 5);
|
||||
if (rc != pcmk_rc_ok) {
|
||||
if (rc == EREMOTEIO) {
|
||||
data->pcmkd_state = pcmk_pacemakerd_state_remote;
|
||||
--
|
||||
2.47.1
|
||||
|
||||
From 2e46b914fb08d346d7b022ba75302f9290034507 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Mon, 4 Aug 2025 10:38:00 -0400
|
||||
Subject: [PATCH 2/2] Med: libpacemaker: Do not retry on ECONNREFUSED in tools.
|
||||
|
||||
This is a regression introduced by e438946787. In that patch, what
|
||||
we're trying to do is retry IPC connections between daemons. If a
|
||||
daemon gets ECONNREFUSED when it initiates an IPC connection, the most
|
||||
likely reason is that another daemon has been killed and is restarting
|
||||
but is not yet ready to accept connections. Waiting and retrying
|
||||
repeatedly is an acceptable way to deal with this.
|
||||
|
||||
However, if a command line tool gets ECONNREFUSED, it's more likely that
|
||||
the problem is the cluster isn't running at all. In this case, waiting
|
||||
and retrying just introduces a delay for a situation that will never be
|
||||
resolved. Reverting just the part in pcmk_cluster_queries.c should fix
|
||||
this problem without affecting any of the daemons - they don't call this
|
||||
code.
|
||||
|
||||
Fixes RHEL-106594
|
||||
---
|
||||
lib/pacemaker/pcmk_cluster_queries.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/pacemaker/pcmk_cluster_queries.c b/lib/pacemaker/pcmk_cluster_queries.c
|
||||
index c1fcf73..bbefcda 100644
|
||||
--- a/lib/pacemaker/pcmk_cluster_queries.c
|
||||
+++ b/lib/pacemaker/pcmk_cluster_queries.c
|
||||
@@ -360,7 +360,7 @@ ipc_connect(data_t *data, enum pcmk_ipc_server server, pcmk_ipc_callback_t cb,
|
||||
pcmk_register_ipc_callback(api, cb, data);
|
||||
}
|
||||
|
||||
- rc = pcmk__connect_ipc_retry_conrefused(api, dispatch_type, 5);
|
||||
+ rc = pcmk__connect_ipc(api, dispatch_type, 5);
|
||||
if (rc != pcmk_rc_ok) {
|
||||
if (rc == EREMOTEIO) {
|
||||
data->pcmkd_state = pcmk_pacemakerd_state_remote;
|
||||
--
|
||||
2.47.1
|
||||
|
||||
413
SOURCES/005-remote_overflow.patch
Normal file
413
SOURCES/005-remote_overflow.patch
Normal file
@ -0,0 +1,413 @@
|
||||
From 264d94dcdb4c6739355f7251b4e9e81256938dbf 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/6] 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 b25e5ce..a4c8b8a 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2008-2024 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 8d21d297629bcc8aebf71bb171c550bcc4532c3f 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/6] 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 | 49 ++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 42 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/lib/common/remote.c b/lib/common/remote.c
|
||||
index a4c8b8a..aa8e762 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -619,16 +619,51 @@ 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 =
|
||||
- pcmk__assert_alloc(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
|
||||
+
|
||||
+ /* @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);
|
||||
|
||||
- crm_trace("Decompressing message data %d bytes into %d bytes",
|
||||
- header->payload_compressed, size_u);
|
||||
+ uncompressed = pcmk__assert_alloc(header->payload_offset + size_u,
|
||||
+ sizeof(char));
|
||||
|
||||
- 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 77a530d1bb867264fa0d42752da44d75ee063830 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/6] 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 pcmk__assert_alloc, 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 | 17 +++++++++++++++--
|
||||
2 files changed, 19 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/include/crm/common/remote_internal.h b/include/crm/common/remote_internal.h
|
||||
index f8c0bea..00f5918 100644
|
||||
--- a/include/crm/common/remote_internal.h
|
||||
+++ b/include/crm/common/remote_internal.h
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
- * Copyright 2008-2024 the Pacemaker project contributors
|
||||
+ * Copyright 2008-2026 the Pacemaker project contributors
|
||||
*
|
||||
* The version control history for this file may have further details.
|
||||
*
|
||||
@@ -15,6 +15,9 @@
|
||||
#include <crm/common/nodes.h> // pcmk_node_variant_remote
|
||||
#include <crm/common/scheduler_types.h> // pcmk_node_t
|
||||
|
||||
+// 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 aa8e762..08b6988 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -623,6 +623,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) {
|
||||
@@ -656,11 +657,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 = pcmk__assert_alloc(header->payload_offset + size_u,
|
||||
- sizeof(char));
|
||||
+ uncompressed = pcmk__assert_alloc(buffer_size, sizeof(char));
|
||||
|
||||
rc = BZ2_bzBuffToBuffDecompress(uncompressed + header->payload_offset,
|
||||
&size_u,
|
||||
@@ -805,6 +812,12 @@ pcmk__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 eaae2d00a2d29c0187832a55a81cf42b39d93a25 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/6] 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 GString, which is a gsize, which is also 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 08b6988..83f050d 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -586,6 +586,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);
|
||||
@@ -594,6 +601,7 @@ pcmk__remote_send_xml(pcmk__remote_t *remote, const xmlNode *msg)
|
||||
pcmk_rc_str(rc), rc);
|
||||
}
|
||||
|
||||
+done:
|
||||
free(iov[0].iov_base);
|
||||
g_free((gchar *) iov[1].iov_base);
|
||||
return rc;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
From 2e097d03f1d93f95162a37a5c21ec46d911af176 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Thu, 28 May 2026 12:56:57 -0400
|
||||
Subject: [PATCH 5/6] Refactor: libcib: Remove an unnecessary coverity
|
||||
suppression.
|
||||
|
||||
With all the previous changes, this suppression is no longer necessary
|
||||
and can be removed.
|
||||
---
|
||||
lib/cib/cib_remote.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/lib/cib/cib_remote.c b/lib/cib/cib_remote.c
|
||||
index baed17b..a64ff95 100644
|
||||
--- a/lib/cib/cib_remote.c
|
||||
+++ b/lib/cib/cib_remote.c
|
||||
@@ -243,7 +243,6 @@ cib_remote_callback_dispatch(gpointer user_data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- // coverity[tainted_data] This can't easily be changed right now
|
||||
msg = pcmk__remote_message_xml(&private->callback);
|
||||
if (msg == NULL) {
|
||||
private->start_time = 0;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
From 2a3c713c3ceab8f5aded9693d09203d18b33bf55 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Lumens <clumens@redhat.com>
|
||||
Date: Wed, 17 Jun 2026 15:55:28 -0400
|
||||
Subject: [PATCH 6/6] 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 83f050d..9ad4b17 100644
|
||||
--- a/lib/common/remote.c
|
||||
+++ b/lib/common/remote.c
|
||||
@@ -620,6 +620,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) {
|
||||
@@ -709,7 +710,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 = pcmk__xml_parse(remote->buffer + header->payload_offset);
|
||||
if (xml == NULL && header->version > REMOTE_MSG_VERSION) {
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
## Where bug reports should be submitted
|
||||
## Leave bug_url undefined to use ClusterLabs default, others define it here
|
||||
%if 0%{?rhel}
|
||||
%global bug_url https://issues.redhat.com/
|
||||
%global bug_url https://github.com/oracle/oracle-linux/
|
||||
%else
|
||||
%if 0%{?fedora}
|
||||
%global bug_url https://bugz.fedoraproject.org/%{name}
|
||||
@ -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.10
|
||||
%global specversion 1
|
||||
%global specversion 3
|
||||
|
||||
## Upstream commit (full commit ID, abbreviated commit ID, or tag) to build
|
||||
%global commit 5693eaeeef06faa1622515963082b5a1731d9fc0
|
||||
@ -230,7 +230,7 @@
|
||||
Name: pacemaker
|
||||
Summary: Scalable High-Availability cluster resource manager
|
||||
Version: %{pcmkversion}
|
||||
Release: %{pcmk_release}.1%{?dist}
|
||||
Release: %{pcmk_release}.0.1%{?dist}
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-or-later
|
||||
Url: https://www.clusterlabs.org/
|
||||
|
||||
@ -247,8 +247,11 @@ Source1: https://codeload.github.com/%{github_owner}/%{nagios_name}/tar.gz
|
||||
Source2: pacemaker.sysusers
|
||||
|
||||
# upstream commits
|
||||
Patch001: 001-ipc_evict.patch
|
||||
Patch002: 002-fewer_messages.patch
|
||||
Patch001: 001-crm_resource_wait.patch
|
||||
Patch002: 002-ipc_connect_retry.patch
|
||||
Patch003: 003-ipc_evict.patch
|
||||
Patch004: 004-fewer_messages.patch
|
||||
Patch005: 005-remote_overflow.patch
|
||||
|
||||
Requires: resource-agents
|
||||
Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release}
|
||||
@ -915,10 +918,22 @@ exit 0
|
||||
%license %{nagios_name}-%{nagios_hash}/COPYING
|
||||
|
||||
%changelog
|
||||
* Wed Feb 18 2026 Chris Lumens <clumens@redhat.com> - 2.1.10-1.1
|
||||
* Tue Jul 14 2026 EL Errata <el-errata_ww@oracle.com> - 2.1.10-3.0.1
|
||||
- Replace bug url [Orabug: 34202300]
|
||||
- Upstream reference in pacemaker crm_report binary [Orabug: 32825154]
|
||||
|
||||
* Tue Jun 30 2026 Chris Lumens <clumens@redhat.com> - 2.1.10-3
|
||||
- Fix integer overflows in remote message decompression code (CVE-2026-10649)
|
||||
- Resolves: RHEL-181150
|
||||
|
||||
* Wed Nov 12 2025 Chris Lumens <clumens@redhat.com> - 2.1.10-2
|
||||
- Handle large timeouts correctly in crm_resource --wait
|
||||
- Do not try to connect to subdaemons before they're respawned
|
||||
- Don't evict IPC clients as long as they're still processing messages
|
||||
- Don't overwhelm the FSA queue with repeated CIB queries
|
||||
- Resolves: RHEL-150167
|
||||
- Resolves: RHEL-45869
|
||||
- Resolves: RHEL-87484
|
||||
- Resolves: RHEL-114894
|
||||
|
||||
* Mon Jun 23 2025 Chris Lumens <clumens@redhat.com> - 2.1.10-1
|
||||
- Rebase on upstream 2.1.10-rc1 release
|
||||
|
||||
Loading…
Reference in New Issue
Block a user