From 97c46401df40ee5d215b8df1033094d5b4d61fca Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Dec 15 2020 18:02:10 +0000 Subject: 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. patch_name: 016-CVE-2020-25654.patch present_in_specfile: true location_in_specfile: 16 squash_commits: true --- diff --git a/daemons/fenced/fenced_commands.c b/daemons/fenced/fenced_commands.c index 8f70dab..2cec9bc 100644 --- a/daemons/fenced/fenced_commands.c +++ b/daemons/fenced/fenced_commands.c @@ -2540,6 +2540,18 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags, 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, pcmk__client_privileged); + } +#endif + crm_element_value_int(request, F_STONITH_CALLOPTS, &call_options); if (is_set(call_options, st_opt_sync_call)) { @@ -2696,27 +2708,43 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags, } 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)) { @@ -2736,6 +2764,11 @@ handle_request(pcmk__client_t *client, uint32_t id, uint32_t flags, done: + if (rc == -EACCES) { + crm_warn("Rejecting IPC request '%s' from unprivileged client %s", + crm_str(op), pcmk__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 */