Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 640f9211a325d1e093fd3c108a97fedae646e86e
Parent: d4dd514faa27f4f7c91205d7525c7f3bc1885aa3
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Mon Mar 28 15:56:08 2011 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Fri Apr 8 09:31:15 2011 -0400
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(a)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)