Skip to content

Commit

Permalink
Fix: ipc: Restore the ability for members of the haclient group to co…
Browse files Browse the repository at this point in the history
…nnect to the cluster
  • Loading branch information
beekhof committed Mar 14, 2013
1 parent 1a53e74 commit 3c9275e
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 61 deletions.
18 changes: 9 additions & 9 deletions lib/ais/plugin.c
@@ -1,16 +1,16 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
*
* 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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
30 changes: 9 additions & 21 deletions lib/ais/utils.c
@@ -1,16 +1,16 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
*
* 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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand Down
42 changes: 21 additions & 21 deletions lib/common/ipc.c
Expand Up @@ -256,13 +256,27 @@ 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);
if (c == NULL) {
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));
Expand All @@ -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);
Expand Down Expand Up @@ -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();

Expand All @@ -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 {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down
13 changes: 13 additions & 0 deletions mcp/corosync.c
Expand Up @@ -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

Expand Down
35 changes: 25 additions & 10 deletions mcp/pacemaker.c
Expand Up @@ -20,6 +20,7 @@
#include <pacemaker.h>

#include <pwd.h>
#include <grp.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
}
}

Expand Down

0 comments on commit 3c9275e

Please sign in to comment.