From 640f9211a325d1e093fd3c108a97fedae646e86e Mon Sep 17 00:00:00 2001 From: Lon Hohberger <lhh@redhat.com> Date: Mon, 28 Mar 2011 15:56:08 -0400 Subject: [PATCH] rgmanager: Allow non-root clustat This allows non-root users access to the running cluster and service states. This requires you to add a user to the 'root' group, matching cman_tool's requirements. Simple backport from RHEL6 / STABLE31 Resolves: rhbz#510300 Signed-off-by: Lon Hohberger <lhh@redhat.com> --- rgmanager/include/message.h | 1 + rgmanager/include/resgroup.h | 3 +++ rgmanager/src/clulib/msg_socket.c | 16 +++++++++++++++- rgmanager/src/clulib/rg_strings.c | 2 ++ rgmanager/src/daemons/main.c | 33 ++++++++++++++++++++++++++++++++- 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/rgmanager/include/message.h b/rgmanager/include/message.h index f987ec6..4b9ae3a 100644 --- a/rgmanager/include/message.h +++ b/rgmanager/include/message.h @@ -89,6 +89,7 @@ typedef struct _msgctx { } cluster_info; struct { int sockfd; + struct ucred cred; int pad; } local_info; } u; diff --git a/rgmanager/include/resgroup.h b/rgmanager/include/resgroup.h index ded11f4..793ad3b 100644 --- a/rgmanager/include/resgroup.h +++ b/rgmanager/include/resgroup.h @@ -187,6 +187,9 @@ int rg_unlock(struct dlm_lksb *p); /* Return codes */ +#define RG_EPERM -18 /* Permission denied */ +#define RG_ERELO -17 /* Relocation failure; service running + on original node */ #define RG_EEXCL -16 /* Service not runnable due to the fact that it is tagged exclusive and there are no diff --git a/rgmanager/src/clulib/msg_socket.c b/rgmanager/src/clulib/msg_socket.c index c392757..4fc9f88 100644 --- a/rgmanager/src/clulib/msg_socket.c +++ b/rgmanager/src/clulib/msg_socket.c @@ -330,6 +330,8 @@ static int sock_msg_accept(msgctx_t *listenctx, msgctx_t *acceptctx) { errno = EINVAL; + struct ucred cred; + socklen_t credlen = sizeof(cred); if (!listenctx || !acceptctx) return -1; @@ -345,6 +347,18 @@ sock_msg_accept(msgctx_t *listenctx, msgctx_t *acceptctx) if (acceptctx->u.local_info.sockfd < 0) return -1; + memset(&cred, 0, sizeof(cred)); + if (getsockopt(acceptctx->u.local_info.sockfd, SOL_SOCKET, + SO_PEERCRED, (void *)&cred, &credlen) < 0) { + perror("getsockopt"); + cred.uid = (uid_t)-1; + cred.gid = (gid_t)-1; + cred.pid = (pid_t)-1; + } + + memcpy(&acceptctx->u.local_info.cred, &cred, + sizeof(cred)); + set_cloexec(acceptctx->u.local_info.sockfd); acceptctx->flags = (SKF_READ | SKF_WRITE); @@ -372,7 +386,7 @@ sock_msg_listen(int me, void *portp, msgctx_t **listen_ctx) set_cloexec(sock); unlink(RGMGR_SOCK); - om = umask(077); + om = umask(0117); su.sun_family = PF_LOCAL; snprintf(su.sun_path, sizeof(su.sun_path), "%s", path); diff --git a/rgmanager/src/clulib/rg_strings.c b/rgmanager/src/clulib/rg_strings.c index 4d1eccb..47b06e0 100644 --- a/rgmanager/src/clulib/rg_strings.c +++ b/rgmanager/src/clulib/rg_strings.c @@ -26,6 +26,8 @@ struct string_val { const struct string_val rg_error_strings[] = { + { RG_EPERM, "Permission denied" }, + { RG_ERELO, "Failed; service running on original owner" }, { RG_EEXCL, "Service not runnable: cannot run exclusive" }, { RG_EDOMAIN, "Service not runnable: restricted failover domain offline" }, { RG_ESCRIPT, "S/Lang Script Error" }, diff --git a/rgmanager/src/daemons/main.c b/rgmanager/src/daemons/main.c index 52e38bc..aa78cef 100644 --- a/rgmanager/src/daemons/main.c +++ b/rgmanager/src/daemons/main.c @@ -32,6 +32,8 @@ #include <msgsimple.h> #include <vf.h> #include <lock.h> +#include <sys/socket.h> +#include <message.h> #include <rg_queue.h> #include <malloc.h> #include <cman-private.h> @@ -428,11 +430,17 @@ do_lockreq(msgctx_t *ctx, int req) int dispatch_msg(msgctx_t *ctx, int nodeid, int need_close) { - int ret = 0, sz = -1, nid; + int ret = 0, sz = -1, nid, read_only = 1; char msgbuf[4096]; generic_msg_hdr *msg_hdr = (generic_msg_hdr *)msgbuf; SmMessageSt *msg_sm = (SmMessageSt *)msgbuf; + if (ctx->type == MSG_CLUSTER) { + read_only = 0; + } else if (ctx->u.local_info.cred.uid == 0) { + read_only = 0; + } + memset(msgbuf, 0, sizeof(msgbuf)); /* Peek-a-boo */ @@ -486,6 +494,10 @@ dispatch_msg(msgctx_t *ctx, int nodeid, int need_close) case RG_LOCK: case RG_UNLOCK: + if (read_only) { + msg_send_simple(ctx, RG_FAIL, RG_EPERM, 0); + goto out; + } if (rg_quorate()) do_lockreq(ctx, msg_hdr->gh_command); break; @@ -498,6 +510,10 @@ dispatch_msg(msgctx_t *ctx, int nodeid, int need_close) break; case RG_ACTION_REQUEST: + if (read_only) { + msg_send_simple(ctx, RG_FAIL, RG_EPERM, 0); + goto out; + } if (sz < (int)sizeof(msg_sm)) { clulog(LOG_ERR, @@ -557,6 +573,11 @@ dispatch_msg(msgctx_t *ctx, int nodeid, int need_close) return 0; case RG_EVENT: + if (read_only) { + msg_send_simple(ctx, RG_FAIL, RG_EPERM, 0); + goto out; + } + /* Service event. Run a dependency check */ if (sz < (int)sizeof(msg_sm)) { clulog(LOG_ERR, @@ -579,6 +600,11 @@ dispatch_msg(msgctx_t *ctx, int nodeid, int need_close) break; case RG_EXITING: + if (read_only) { + msg_send_simple(ctx, RG_FAIL, RG_EPERM, 0); + goto out; + } + if (!member_online(msg_hdr->gh_arg1)) break; @@ -589,6 +615,11 @@ dispatch_msg(msgctx_t *ctx, int nodeid, int need_close) break; case VF_MESSAGE: + if (read_only) { + msg_send_simple(ctx, RG_FAIL, RG_EPERM, 0); + goto out; + } + /* Ignore; our VF thread handles these - except for VF_CURRENT XXX (bad design) */ if (msg_hdr->gh_arg1 == VF_CURRENT) -- 1.7.3.4