diff --git a/CVE-2020-25654.patch b/CVE-2020-25654.patch new file mode 100644 index 0000000000000000000000000000000000000000..048810aae7b1cc439cb5f58f98ba34c282bf64cb --- /dev/null +++ b/CVE-2020-25654.patch @@ -0,0 +1,514 @@ +From 3d1a7dc0c545c1ffba216df5c82b5ee3e3c7b3bf Mon Sep 17 00:00:00 2001 +From: Ken Gaillot +Date: Fri, 9 Oct 2020 09:56:03 -0500 +Subject: [PATCH 1/7] Log: executor: show CRM_OP_REGISTER rc in debug message + +Previously, process_lrmd_signon() would add the rc to the client reply +but not pass it back to process_lrmd_message(), which would always log "OK" in +its debug message, even if the sign-on was rejected. +--- + daemons/execd/execd_commands.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c +index 9ded90c..aadbc4d 100644 +--- a/daemons/execd/execd_commands.c ++++ b/daemons/execd/execd_commands.c +@@ -1517,10 +1517,10 @@ free_rsc(gpointer data) + free(rsc); + } + +-static xmlNode * +-process_lrmd_signon(crm_client_t *client, xmlNode *request, int call_id) ++static int ++process_lrmd_signon(crm_client_t *client, xmlNode *request, int call_id, ++ xmlNode **reply) + { +- xmlNode *reply = NULL; + int rc = pcmk_ok; + const char *is_ipc_provider = crm_element_value(request, F_LRMD_IS_IPC_PROVIDER); + const char *protocol_version = crm_element_value(request, F_LRMD_PROTOCOL_VERSION); +@@ -1531,18 +1531,19 @@ process_lrmd_signon(crm_client_t *client, xmlNode *request, int call_id) + rc = -EPROTO; + } + +- reply = create_lrmd_reply(__FUNCTION__, rc, call_id); +- crm_xml_add(reply, F_LRMD_OPERATION, CRM_OP_REGISTER); +- crm_xml_add(reply, F_LRMD_CLIENTID, client->id); +- crm_xml_add(reply, F_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION); +- + if (crm_is_true(is_ipc_provider)) { + // This is a remote connection from a cluster node's controller + #ifdef SUPPORT_REMOTE + ipc_proxy_add_provider(client); + #endif + } +- return reply; ++ ++ *reply = create_lrmd_reply(__func__, rc, call_id); ++ crm_xml_add(*reply, F_LRMD_OPERATION, CRM_OP_REGISTER); ++ crm_xml_add(*reply, F_LRMD_CLIENTID, client->id); ++ crm_xml_add(*reply, F_LRMD_PROTOCOL_VERSION, LRMD_PROTOCOL_VERSION); ++ ++ return rc; + } + + static int +@@ -1854,7 +1855,7 @@ process_lrmd_message(crm_client_t * client, uint32_t id, xmlNode * request) + #endif + do_reply = 1; + } else if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) { +- reply = process_lrmd_signon(client, request, call_id); ++ rc = process_lrmd_signon(client, request, call_id, &reply); + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) { + rc = process_lrmd_rsc_register(client, id, request); +-- +1.8.3.1 + + +From d4cc1949292aaa42368e2871a04e67f65f22c154 Mon Sep 17 00:00:00 2001 +From: Ken Gaillot +Date: Fri, 9 Oct 2020 15:16:39 -0500 +Subject: [PATCH 2/7] Low: executor: mark controller connections to + pacemaker-remoted as privileged + +Previously, crm_client_flag_ipc_privileged was only set when local clients connected +(as root or hacluster). Now, set it when pacemaker-remoted successfully +completes the TLS handshake with a remote client (i.e., the controller on a +cluster node). + +This has no effect as of this commit but will with later commits. +--- + daemons/execd/remoted_tls.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/daemons/execd/remoted_tls.c b/daemons/execd/remoted_tls.c +index cd7cbe5..ea9cf3e 100644 +--- a/daemons/execd/remoted_tls.c ++++ b/daemons/execd/remoted_tls.c +@@ -74,6 +74,11 @@ remoted__read_handshake_data(crm_client_t *client) + client->remote->tls_handshake_complete = TRUE; + crm_notice("Remote client connection accepted"); + ++ /* Only a client with access to the TLS key can connect, so we can treat ++ * it as privileged. ++ */ ++ set_bit(client->flags, crm_client_flag_ipc_privileged); ++ + // Alert other clients of the new connection + notify_of_new_client(client); + return 0; +-- +1.8.3.1 + + +From bb6ae415a534fa9f1bd1ec06e0a0b4c64b1e8530 Mon Sep 17 00:00:00 2001 +From: Ken Gaillot +Date: Thu, 15 Oct 2020 15:33:13 -0500 +Subject: [PATCH 3/7] Low: executor: return appropriate error code when no + remote support + +--- + daemons/execd/execd_commands.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c +index aadbc4d..84e9c40 100644 +--- a/daemons/execd/execd_commands.c ++++ b/daemons/execd/execd_commands.c +@@ -1532,9 +1532,11 @@ process_lrmd_signon(crm_client_t *client, xmlNode *request, int call_id, + } + + if (crm_is_true(is_ipc_provider)) { +- // This is a remote connection from a cluster node's controller + #ifdef SUPPORT_REMOTE ++ // This is a remote connection from a cluster node's controller + ipc_proxy_add_provider(client); ++#else ++ rc = -EPROTONOSUPPORT; + #endif + } + +@@ -1852,6 +1854,8 @@ process_lrmd_message(crm_client_t * client, uint32_t id, xmlNode * request) + if (crm_str_eq(op, CRM_OP_IPC_FWD, TRUE)) { + #ifdef SUPPORT_REMOTE + ipc_proxy_forward_client(client, request); ++#else ++ rc = -EPROTONOSUPPORT; + #endif + do_reply = 1; + } else if (crm_str_eq(op, CRM_OP_REGISTER, TRUE)) { +-- +1.8.3.1 + + +From 6fdf576fe506837099561a0fc6409fc315a9f2b7 Mon Sep 17 00:00:00 2001 +From: Ken Gaillot +Date: Thu, 15 Oct 2020 15:33:57 -0500 +Subject: [PATCH 4/7] High: executor: restrict certain IPC requests to + Pacemaker daemons + +The executor IPC API allows clients to register resources, request agent +execution, and so forth. + +If ACLs are enabled, this could allow an ACL-restricted user to bypass ACLs and +execute any code as root. (If ACLs are not enabled, users in the haclient group +have full access to the CIB, which already gives them that ability, so there is +no additional exposure in that case.) + +When ACLs are supported, this commit effectively disables the executor IPC API +for clients that aren't connecting as root or hacluster. Such clients can only +register and poke now. +--- + daemons/execd/execd_commands.c | 91 +++++++++++++++++++++++++++++++++--------- + 1 file changed, 73 insertions(+), 18 deletions(-) + +diff --git a/daemons/execd/execd_commands.c b/daemons/execd/execd_commands.c +index 84e9c40..e217ce7 100644 +--- a/daemons/execd/execd_commands.c ++++ b/daemons/execd/execd_commands.c +@@ -1533,8 +1533,12 @@ process_lrmd_signon(crm_client_t *client, xmlNode *request, int call_id, + + if (crm_is_true(is_ipc_provider)) { + #ifdef SUPPORT_REMOTE +- // This is a remote connection from a cluster node's controller +- ipc_proxy_add_provider(client); ++ if ((client->remote != NULL) && client->remote->tls_handshake_complete) { ++ // This is a remote connection from a cluster node's controller ++ ipc_proxy_add_provider(client); ++ } else { ++ rc = -EACCES; ++ } + #else + rc = -EPROTONOSUPPORT; + #endif +@@ -1848,12 +1852,26 @@ process_lrmd_message(crm_client_t * client, uint32_t id, xmlNode * request) + int do_notify = 0; + xmlNode *reply = NULL; + ++ bool allowed = true; ++ ++#if ENABLE_ACL ++ /* Certain IPC commands may be done only by privileged users (i.e. root or ++ * hacluster) when ACLs are enabled, because they would otherwise provide a ++ * means of bypassing ACLs. ++ */ ++ allowed = is_set(client->flags, crm_client_flag_ipc_privileged); ++#endif ++ + crm_trace("Processing %s operation from %s", op, client->id); + crm_element_value_int(request, F_LRMD_CALLID, &call_id); + + if (crm_str_eq(op, CRM_OP_IPC_FWD, TRUE)) { + #ifdef SUPPORT_REMOTE +- ipc_proxy_forward_client(client, request); ++ if (allowed) { ++ ipc_proxy_forward_client(client, request); ++ } else { ++ rc = -EACCES; ++ } + #else + rc = -EPROTONOSUPPORT; + #endif +@@ -1862,38 +1880,70 @@ process_lrmd_message(crm_client_t * client, uint32_t id, xmlNode * request) + rc = process_lrmd_signon(client, request, call_id, &reply); + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_REG, TRUE)) { +- rc = process_lrmd_rsc_register(client, id, request); +- do_notify = 1; ++ if (allowed) { ++ rc = process_lrmd_rsc_register(client, id, request); ++ do_notify = 1; ++ } else { ++ rc = -EACCES; ++ } + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_INFO, TRUE)) { +- reply = process_lrmd_get_rsc_info(request, call_id); ++ if (allowed) { ++ reply = process_lrmd_get_rsc_info(request, call_id); ++ } else { ++ rc = -EACCES; ++ } + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_UNREG, TRUE)) { +- rc = process_lrmd_rsc_unregister(client, id, request); +- /* don't notify anyone about failed un-registers */ +- if (rc == pcmk_ok || rc == -EINPROGRESS) { +- do_notify = 1; ++ if (allowed) { ++ rc = process_lrmd_rsc_unregister(client, id, request); ++ /* don't notify anyone about failed un-registers */ ++ if (rc == pcmk_ok || rc == -EINPROGRESS) { ++ do_notify = 1; ++ } ++ } else { ++ rc = -EACCES; + } + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_EXEC, TRUE)) { +- rc = process_lrmd_rsc_exec(client, id, request); ++ if (allowed) { ++ rc = process_lrmd_rsc_exec(client, id, request); ++ } else { ++ rc = -EACCES; ++ } + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_RSC_CANCEL, TRUE)) { +- rc = process_lrmd_rsc_cancel(client, id, request); ++ if (allowed) { ++ rc = process_lrmd_rsc_cancel(client, id, request); ++ } else { ++ rc = -EACCES; ++ } + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_POKE, TRUE)) { + do_notify = 1; + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_CHECK, TRUE)) { +- xmlNode *data = get_message_xml(request, F_LRMD_CALLDATA); +- const char *timeout = crm_element_value(data, F_LRMD_WATCHDOG); +- CRM_LOG_ASSERT(data != NULL); +- check_sbd_timeout(timeout); ++ if (allowed) { ++ xmlNode *data = get_message_xml(request, F_LRMD_CALLDATA); ++ ++ CRM_LOG_ASSERT(data != NULL); ++ check_sbd_timeout(crm_element_value(data, F_LRMD_WATCHDOG)); ++ } else { ++ rc = -EACCES; ++ } + } else if (crm_str_eq(op, LRMD_OP_ALERT_EXEC, TRUE)) { +- rc = process_lrmd_alert_exec(client, id, request); ++ if (allowed) { ++ rc = process_lrmd_alert_exec(client, id, request); ++ } else { ++ rc = -EACCES; ++ } + do_reply = 1; + } else if (crm_str_eq(op, LRMD_OP_GET_RECURRING, TRUE)) { +- reply = process_lrmd_get_recurring(request, call_id); ++ if (allowed) { ++ reply = process_lrmd_get_recurring(request, call_id); ++ } else { ++ rc = -EACCES; ++ } + do_reply = 1; + } else { + rc = -EOPNOTSUPP; +@@ -1902,6 +1952,11 @@ process_lrmd_message(crm_client_t * client, uint32_t id, xmlNode * request) + crm_log_xml_warn(request, "UnknownOp"); + } + ++ if (rc == -EACCES) { ++ crm_warn("Rejecting IPC request '%s' from unprivileged client %s", ++ op, crm_client_name(client)); ++ } ++ + crm_debug("Processed %s operation from %s: rc=%d, reply=%d, notify=%d", + op, client->id, rc, do_reply, do_notify); + +-- +1.8.3.1 + + +From 38397e6a04a4b8a16771e57b5b19fc0f7111063b Mon Sep 17 00:00:00 2001 +From: Ken Gaillot +Date: Fri, 9 Oct 2020 11:16:43 -0500 +Subject: [PATCH 5/7] Low: pacemakerd: check client for NULL before using it + +... to guard against bugs in client tracking +--- + daemons/pacemakerd/pacemakerd.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c +index d8ff53d..278b48b 100644 +--- a/daemons/pacemakerd/pacemakerd.c ++++ b/daemons/pacemakerd/pacemakerd.c +@@ -560,9 +560,12 @@ pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) + uint32_t id = 0; + uint32_t flags = 0; + const char *task = NULL; ++ xmlNode *msg = NULL; + crm_client_t *c = crm_client_get(qbc); +- xmlNode *msg = crm_ipcs_recv(c, data, size, &id, &flags); + ++ CRM_CHECK(c != NULL, return 0); ++ ++ msg = crm_ipcs_recv(c, data, size, &id, &flags); + crm_ipcs_send_ack(c, id, flags, "ack", __FUNCTION__, __LINE__); + if (msg == NULL) { + return 0; +-- +1.8.3.1 + + +From 03d1f5861229b3b28728fa0eabfc99ddc9bccaa4 Mon Sep 17 00:00:00 2001 +From: Ken Gaillot +Date: Fri, 9 Oct 2020 11:17:18 -0500 +Subject: [PATCH 6/7] High: pacemakerd: ignore shutdown requests from + unprivileged users + +The pacemakerd IPC API supports a shutdown request, along with a +command-line interface for using it (pacemakerd --shutdown). + +Only the haclient group has access to the IPC. Without ACLs, that group can +already shut down Pacemaker via the CIB, so there's no security implication. + +However, it might not be desired to allow ACL-restricted users to shut down +Pacemaker, so block users other than root or hacluster if ACLs are supported. +--- + daemons/pacemakerd/pacemakerd.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/daemons/pacemakerd/pacemakerd.c b/daemons/pacemakerd/pacemakerd.c +index 278b48b..ebb14e8 100644 +--- a/daemons/pacemakerd/pacemakerd.c ++++ b/daemons/pacemakerd/pacemakerd.c +@@ -573,10 +573,26 @@ pcmk_ipc_dispatch(qb_ipcs_connection_t * qbc, void *data, size_t size) + + task = crm_element_value(msg, F_CRM_TASK); + if (crm_str_eq(task, CRM_OP_QUIT, TRUE)) { +- /* Time to quit */ +- crm_notice("Shutting down in response to ticket %s (%s)", +- crm_element_value(msg, F_CRM_REFERENCE), crm_element_value(msg, F_CRM_ORIGIN)); +- pcmk_shutdown(15); ++ bool allowed = true; ++ ++#if ENABLE_ACL ++ /* Only allow privileged users (i.e. root or hacluster) ++ * to shut down Pacemaker from the command line (or direct IPC). ++ * ++ * We only check when ACLs are enabled, because without them, any client ++ * with IPC access could shut down Pacemaker via the CIB anyway. ++ */ ++ allowed = is_set(c->flags, crm_client_flag_ipc_privileged); ++#endif ++ if (allowed) { ++ crm_notice("Shutting down in response to IPC request %s from %s", ++ crm_element_value(msg, F_CRM_REFERENCE), ++ crm_element_value(msg, F_CRM_ORIGIN)); ++ pcmk_shutdown(15); ++ } else { ++ crm_warn("Ignoring shutdown request from unprivileged client %s", ++ crm_client_name(c)); ++ } + + } else if (crm_str_eq(task, CRM_OP_RM_NODE_CACHE, TRUE)) { + /* Send to everyone */ +-- +1.8.3.1 + + +From 5fcb1e923d2e900da672306fb82a946a0af5e641 Mon Sep 17 00:00:00 2001 +From: Ken Gaillot +Date: Fri, 9 Oct 2020 11:55:26 -0500 +Subject: [PATCH 7/7] Fix: fencer: restrict certain IPC requests to privileged + users + +The fencer IPC API allows clients to register fence devices. + +If ACLs are enabled, this could allow an ACL-restricted user to bypass ACLs to +configure fencing. If the user is able to install executables to the standard +fencing agent locations, have arbitrary code executed as root (the standard +locations generally require root for write access, so that is unlikely to be an +issue). + +If ACLs are not enabled, users in the haclient group have full access to the +CIB, which already gives them these capabilities, so there is no additional +exposure in that case. + +This commit does not restrict unprivileged users from using other fencing API, +such as requesting actual fencing. +--- + daemons/fenced/fenced_commands.c | 41 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 37 insertions(+), 4 deletions(-) + +diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c +index 9d3f924..d965d7c 100644 +--- a/daemons/fenced/fenced_commands.c ++++ b/daemons/fenced/fenced_commands.c +@@ -2455,6 +2455,18 @@ handle_request(crm_client_t * client, uint32_t id, uint32_t flags, xmlNode * req + const char *op = crm_element_value(request, F_STONITH_OPERATION); + const char *client_id = crm_element_value(request, F_STONITH_CLIENTID); + ++ bool allowed = true; ++ ++#if ENABLE_ACL ++ /* IPC commands related to fencing configuration may be done only by ++ * privileged users (i.e. root or hacluster) when ACLs are supported, ++ * because all other users should go through the CIB to have ACLs applied. ++ */ ++ if (client != NULL) { ++ allowed = is_set(client->flags, crm_client_flag_ipc_privileged); ++ } ++#endif ++ + crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options); + + if (is_set(call_options, st_opt_sync_call)) { +@@ -2604,27 +2616,43 @@ handle_request(crm_client_t * client, uint32_t id, uint32_t flags, xmlNode * req + } else if (crm_str_eq(op, STONITH_OP_DEVICE_ADD, TRUE)) { + const char *device_id = NULL; + +- rc = stonith_device_register(request, &device_id, FALSE); ++ if (allowed) { ++ rc = stonith_device_register(request, &device_id, FALSE); ++ } else { ++ rc = -EACCES; ++ } + do_stonith_notify_device(call_options, op, rc, device_id); + + } else if (crm_str_eq(op, STONITH_OP_DEVICE_DEL, TRUE)) { + xmlNode *dev = get_xpath_object("//" F_STONITH_DEVICE, request, LOG_ERR); + const char *device_id = crm_element_value(dev, XML_ATTR_ID); + +- rc = stonith_device_remove(device_id, FALSE); ++ if (allowed) { ++ rc = stonith_device_remove(device_id, FALSE); ++ } else { ++ rc = -EACCES; ++ } + do_stonith_notify_device(call_options, op, rc, device_id); + + } else if (crm_str_eq(op, STONITH_OP_LEVEL_ADD, TRUE)) { + char *device_id = NULL; + +- rc = stonith_level_register(request, &device_id); ++ if (allowed) { ++ rc = stonith_level_register(request, &device_id); ++ } else { ++ rc = -EACCES; ++ } + do_stonith_notify_level(call_options, op, rc, device_id); + free(device_id); + + } else if (crm_str_eq(op, STONITH_OP_LEVEL_DEL, TRUE)) { + char *device_id = NULL; + +- rc = stonith_level_remove(request, &device_id); ++ if (allowed) { ++ rc = stonith_level_remove(request, &device_id); ++ } else { ++ rc = -EACCES; ++ } + do_stonith_notify_level(call_options, op, rc, device_id); + + } else if(safe_str_eq(op, CRM_OP_RM_NODE_CACHE)) { +@@ -2644,6 +2672,11 @@ handle_request(crm_client_t * client, uint32_t id, uint32_t flags, xmlNode * req + + done: + ++ if (rc == -EACCES) { ++ crm_warn("Rejecting IPC request '%s' from unprivileged client %s", ++ crm_str(op), crm_client_name(client)); ++ } ++ + /* Always reply unless the request is in process still. + * If in progress, a reply will happen async after the request + * processing is finished */ +-- +1.8.3.1 + diff --git a/pacemaker.spec b/pacemaker.spec index 0f22b991c2129c239d2cd6abdc5c475b31f45250..a993a5740e8c5e41f393777f067cf3a8bbefbc40 100644 --- a/pacemaker.spec +++ b/pacemaker.spec @@ -14,7 +14,7 @@ ## can be incremented to build packages reliably considered "newer" ## than previously built packages with the same pcmkversion) %global pcmkversion 2.0.3 -%global specversion 2 +%global specversion 3 ## Upstream commit (or git tag, such as "Pacemaker-" plus the ## {pcmkversion} macro for an official release) to use for this package @@ -131,6 +131,7 @@ Source1: https://github.com/%{github_owner}/%{nagios_name}/archive/%{nagio # --- Patch0: Build-fix-unability-to-build-with-Inkscape-1.0-beta-.patch Patch1: Resolve-the-failure-of-time-matching-in-test-cases.patch +Patch2: CVE-2020-25654.patch Requires: resource-agents Requires: %{name}-libs%{?_isa} = %{version}-%{release} @@ -339,6 +340,7 @@ monitor resources. %__scm_setup_git %patch0 -p1 %patch1 -p1 +%patch2 -p1 %build @@ -701,6 +703,12 @@ exit 0 %license %{nagios_name}-%{nagios_hash}/COPYING %changelog +* Sat Sep 03 2022 jiangxinyu - 2.0.3-3 +- Type:cves +- ID:CVE-2020-25654 +- SUG:NA +- DESC:fix CVE-2020-25654 + * Tue Mar 23 2021 jiangxinyu - 2.0.3-2 - Add 'Resolve-the-failure-of-time-matching-in-test-cases.patch' file 2.0.3-2