diff --git a/lib/ais/plugin.c b/lib/ais/plugin.c index f2d9e09a3b7..be6af6e3248 100644 --- a/lib/ais/plugin.c +++ b/lib/ais/plugin.c @@ -1,16 +1,16 @@ /* * Copyright (C) 2004 Andrew Beekhof - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAA @@ -203,14 +203,14 @@ struct corosync_service_engine pcmk_service_handler = { .name = (char *)"Pacemaker Cluster Manager "PACKAGE_VERSION, .id = PCMK_SERVICE_ID, .private_data_size = 0, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, + .flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, .allow_inquorate = CS_LIB_ALLOW_INQUORATE, .lib_init_fn = pcmk_ipc_connect, .lib_exit_fn = pcmk_ipc_exit, .exec_init_fn = pcmk_startup, .exec_exit_fn = pcmk_shutdown, .config_init_fn = pcmk_config_init, - .priority = 50, + .priority = 50, .lib_engine = pcmk_lib_service, .lib_engine_count = sizeof (pcmk_lib_service) / sizeof (struct corosync_lib_handler), .exec_engine = pcmk_exec_service, @@ -492,7 +492,7 @@ pcmk_wait_dispatch(void *arg) } /* Broadcast the fact that one of our processes died - * + * * Try to get some logging of the cause out first though * because we're probably about to get fenced * @@ -674,13 +674,13 @@ pcmk_startup(struct corosync_api_v1 *init_with) } /* - static void ais_print_node(const char *prefix, struct totem_ip_address *host) + static void ais_print_node(const char *prefix, struct totem_ip_address *host) { int len = 0; char *buffer = NULL; ais_malloc0(buffer, INET6_ADDRSTRLEN+1); - + inet_ntop(host->family, host->addr, buffer, INET6_ADDRSTRLEN); len = strlen(buffer); @@ -1026,7 +1026,7 @@ pcmk_ipc(void *conn, ais_void_ptr * msg) transient = FALSE; } #if 0 - /* If this check fails, the order of pcmk_children probably + /* If this check fails, the order of pcmk_children probably * doesn't match that of the crm_ais_msg_types enum */ AIS_CHECK(transient || mutable->sender.pid == pcmk_children[type].pid, diff --git a/lib/ais/utils.c b/lib/ais/utils.c index a9774adcfdc..465e381cef6 100644 --- a/lib/ais/utils.c +++ b/lib/ais/utils.c @@ -1,16 +1,16 @@ /* * Copyright (C) 2004 Andrew Beekhof - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA @@ -63,7 +63,7 @@ log_ais_message(int level, const AIS_Message * msg) } /* -static gboolean ghash_find_by_uname(gpointer key, gpointer value, gpointer user_data) +static gboolean ghash_find_by_uname(gpointer key, gpointer value, gpointer user_data) { crm_node_t *node = value; int id = GPOINTER_TO_INT(user_data); @@ -140,6 +140,7 @@ spawn_child(crm_child_t * child) { int lpc = 0; uid_t uid = 0; + gid_t gid = 0; struct rlimit oflimits; gboolean use_valgrind = FALSE; gboolean use_callgrind = FALSE; @@ -174,10 +175,11 @@ spawn_child(crm_child_t * child) } if (child->uid) { - if (pcmk_user_lookup(child->uid, &uid, NULL) < 0) { + if (pcmk_user_lookup(child->uid, &uid, &gid) < 0) { ais_err("Invalid uid (%s) specified for %s", child->uid, child->name); return FALSE; } + ais_info("Using uid=%u and group=%u for process %s", uid, gid, child->name); } child->pid = fork(); @@ -206,22 +208,8 @@ spawn_child(crm_child_t * child) } opts_default[0] = ais_strdup(child->command);; -#if 0 - /* Dont set the group for now - it prevents connection to the cluster */ - if (gid && setgid(gid) < 0) { - ais_perror("Could not set group to %d", gid); - } -#endif - - if (uid) { - struct passwd *pwent = getpwuid(uid); - - if (pwent == NULL) { - ais_perror("Cannot get password entry of uid: %d", uid); - - } else if (initgroups(pwent->pw_name, pwent->pw_gid) < 0) { - ais_perror("Cannot initalize groups for %s (uid=%d)", pwent->pw_name, uid); - } + if (uid && initgroups(child->uid, gid) < 0) { + ais_perror("Cannot initalize groups for %s", child->uid); } if (uid && setuid(uid) < 0) { diff --git a/lib/common/ipc.c b/lib/common/ipc.c index bab3f25bc8c..536e75a9e97 100644 --- a/lib/common/ipc.c +++ b/lib/common/ipc.c @@ -256,6 +256,7 @@ crm_client_cleanup(void) crm_client_t * crm_client_new(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) { + static gid_t crm_gid = 0; crm_client_t *client = NULL; CRM_LOG_ASSERT(c); @@ -263,6 +264,19 @@ crm_client_new(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) return NULL; } + if (crm_gid == 0 && crm_user_lookup(CRM_DAEMON_USER, NULL, &crm_gid) < 0) { + static bool have_error = FALSE; + if(have_error == FALSE) { + crm_warn("Could not find group for user %s", CRM_DAEMON_USER); + have_error = TRUE; + } + } + + if(crm_gid != 0 && gid != 0) { + crm_trace("Giving access to group %u", crm_gid); + qb_ipcs_connection_auth_set(c, -1, crm_gid, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + } + crm_client_init(); client = calloc(1, sizeof(crm_client_t)); @@ -276,16 +290,7 @@ crm_client_new(qb_ipcs_connection_t * c, uid_t uid, gid_t gid) crm_info("Connecting %p for uid=%d gid=%d pid=%u id=%s", c, uid, gid, client->pid, client->id); #if ENABLE_ACL - { - struct group *crm_grp = NULL; - - crm_grp = getgrnam(CRM_DAEMON_GROUP); - if (crm_grp) { - qb_ipcs_connection_auth_set(c, -1, crm_grp->gr_gid, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - } - client->user = uid2username(uid); - } + client->user = uid2username(uid); #endif g_hash_table_insert(client_connections, c, client); @@ -975,7 +980,6 @@ crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, in struct iovec *iov; static uint32_t id = 0; struct crm_ipc_response_header *header; - char *buffer = NULL; crm_ipc_init(); @@ -995,7 +999,6 @@ crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, in if (rc < 0) { crm_warn("Sending to %s (%p) is disabled until pending reply is recieved", client->name, client->ipc); - free(buffer); return -EALREADY; } else { @@ -1017,21 +1020,21 @@ crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, in ms_timeout = 5000; } - crm_trace("Sending from client: %s request id: %d bytes: %u timeout:%d msg: %.200s...", - client->name, header->qb.id, header->qb.size, ms_timeout, buffer); + crm_trace("Sending from client: %s request id: %d bytes: %u timeout:%d msg...", + client->name, header->qb.id, header->qb.size, ms_timeout); if (ms_timeout > 0) { rc = internal_ipc_send_request(client, iov, ms_timeout); if (rc <= 0) { - crm_trace("Failed to send from client %s request %d with %u bytes: %.200s...", - client->name, header->qb.id, header->qb.size, buffer); + crm_trace("Failed to send from client %s request %d with %u bytes...", + client->name, header->qb.id, header->qb.size); goto send_cleanup; } else if (is_not_set(flags, crm_ipc_client_response)) { - crm_trace("Message sent, not waiting for reply to %d from %s to %u bytes: %.200s...", - header->qb.id, client->name, header->qb.size, buffer); + crm_trace("Message sent, not waiting for reply to %d from %s to %u bytes...", + header->qb.id, client->name, header->qb.size); goto send_cleanup; } @@ -1073,19 +1076,16 @@ crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, in } else if (rc == -ETIMEDOUT) { crm_warn("Request %d to %s (%p) failed: %s (%ld) after %dms", header->qb.id, client->name, client->ipc, pcmk_strerror(rc), rc, ms_timeout); - crm_info("Request was %.120s", buffer); crm_write_blackbox(0, NULL); } else if (rc <= 0) { crm_warn("Request %d to %s (%p) failed: %s (%ld)", header->qb.id, client->name, client->ipc, pcmk_strerror(rc), rc); - crm_info("Request was %.120s", buffer); } free(header); free(iov[1].iov_base); free(iov); - free(buffer); return rc; } diff --git a/mcp/corosync.c b/mcp/corosync.c index adc57cc54d6..5aa82acd8a9 100644 --- a/mcp/corosync.c +++ b/mcp/corosync.c @@ -581,6 +581,19 @@ read_config(void) #if HAVE_CONFDB confdb_finalize(config); #elif HAVE_CMAP + if(local_handle){ + gid_t gid = 0; + if (crm_user_lookup(CRM_DAEMON_USER, NULL, &gid) < 0) { + crm_warn("No group found for user %s", CRM_DAEMON_USER); + + } else { + char key[PATH_MAX]; + snprintf(key, PATH_MAX, "uidgid.gid.%u", gid); + rc = cmap_set_uint8(local_handle, key, 1); + crm_notice("Configured corosync to accept connections from group %u: %s (%d)", + gid, ais_error2text(rc), rc); + } + } cmap_finalize(local_handle); #endif diff --git a/mcp/pacemaker.c b/mcp/pacemaker.c index 2ed40ed8cb5..6d6a6dcae8e 100644 --- a/mcp/pacemaker.c +++ b/mcp/pacemaker.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -226,12 +227,14 @@ start_child(pcmk_child_t * child) { int lpc = 0; uid_t uid = 0; + gid_t gid = 0; struct rlimit oflimits; gboolean use_valgrind = FALSE; gboolean use_callgrind = FALSE; const char *devnull = "/dev/null"; const char *env_valgrind = getenv("PCMK_valgrind_enabled"); const char *env_callgrind = getenv("PCMK_callgrind_enabled"); + enum cluster_type_e stack = get_cluster_type(); child->active_before_startup = FALSE; @@ -261,6 +264,14 @@ start_child(pcmk_child_t * child) use_valgrind = FALSE; } + if (child->uid) { + if (crm_user_lookup(child->uid, &uid, &gid) < 0) { + crm_err("Invalid user (%s) for %s: not found", child->uid, child->name); + return FALSE; + } + crm_info("Using uid=%u and group=%u for process %s", uid, gid, child->name); + } + child->pid = fork(); CRM_ASSERT(child->pid != -1); @@ -292,17 +303,21 @@ start_child(pcmk_child_t * child) } opts_default[0] = strdup(child->command);; -#if 0 - /* Dont set the group for now - it prevents connection to the cluster */ - if (gid && setgid(gid) < 0) { - crm_perror("Could not set group to %d", gid); - } -#endif + if(gid) { + if(stack == pcmk_cluster_corosync) { + /* Drop root privileges completely + * + * We can do this because we set uidgid.gid.${gid}=1 + * via CMAP which allows these processes to connect to + * corosync + */ + if (setgid(gid) < 0) { + crm_perror(LOG_ERR, "Could not set group to %d", gid); + } - if (child->uid) { - if (crm_user_lookup(child->uid, &uid, NULL) < 0) { - crm_err("Invalid uid (%s) specified for %s", child->uid, child->name); - return TRUE; + /* Keep the root group (so we can access corosync), but add the haclient group (so we can access ipc) */ + } else if (initgroups(child->uid, gid) < 0) { + crm_err("Cannot initalize groups for %s: %s (%d)", child->uid, pcmk_strerror(errno), errno); } }