summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCsaba Henk <csaba@gluster.com>2011-09-13 13:12:38 +0200
committerVijay Bellur <vijay@gluster.com>2011-09-22 05:23:54 -0700
commit7e04913aa6f4ddb45e95099ef648564bf90da0b3 (patch)
treec456a74980b0dcc7eaa6338ee46454a55bf16156
parent2ab00369e7ef99d287dad5301d2f334dcfd67a70 (diff)
gsyncd: control rsync target
- require/perform rsync invocation with unprotected args (so that target is revealed to gateway program) - make use of some procfs wizardry to find gsyncd sibling and match rsync target against its working directory Change-Id: Iae1e39b0e61f22563c0f2a2e0605567e0d1902df BUG: 2825 Reviewed-on: http://review.gluster.com/461 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vijay@gluster.com>
-rw-r--r--xlators/features/marker/utils/src/Makefile.am4
-rw-r--r--xlators/features/marker/utils/src/gsyncd.c122
-rw-r--r--xlators/features/marker/utils/src/procdiggy.c124
-rw-r--r--xlators/features/marker/utils/src/procdiggy.h26
-rw-r--r--xlators/features/marker/utils/syncdaemon/gsyncd.py2
5 files changed, 258 insertions, 20 deletions
diff --git a/xlators/features/marker/utils/src/Makefile.am b/xlators/features/marker/utils/src/Makefile.am
index 74e2b3ef5..73c99cb76 100644
--- a/xlators/features/marker/utils/src/Makefile.am
+++ b/xlators/features/marker/utils/src/Makefile.am
@@ -2,12 +2,14 @@ gsyncddir = $(libexecdir)/glusterfs
gsyncd_PROGRAMS = gsyncd
-gsyncd_SOURCES = gsyncd.c
+gsyncd_SOURCES = gsyncd.c procdiggy.c
gsyncd_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
gsyncd_LDFLAGS = $(GF_LDFLAGS) $(GF_GLUSTERFS_LDFLAGS)
+noinst_HEADERS = procdiggy.h
+
AM_CFLAGS = -fPIC -Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS)\
-I$(top_srcdir)/libglusterfs/src\
-DGSYNCD_PREFIX=\"$(libexecdir)/glusterfs\"\
diff --git a/xlators/features/marker/utils/src/gsyncd.c b/xlators/features/marker/utils/src/gsyncd.c
index cebca1aea..d3fa2d325 100644
--- a/xlators/features/marker/utils/src/gsyncd.c
+++ b/xlators/features/marker/utils/src/gsyncd.c
@@ -30,10 +30,12 @@
#include "common-utils.h"
#include "run.h"
+#include "procdiggy.h"
#define _GLUSTERD_CALLED_ "_GLUSTERD_CALLED_"
#define _GSYNCD_DISPATCHED_ "_GSYNCD_DISPATCHED_"
#define GSYNCD_CONF "geo-replication/gsyncd.conf"
+#define GSYNCD_PY "gsyncd.py"
#define RSYNC "rsync"
int restricted = 0;
@@ -128,9 +130,12 @@ invoke_gsyncd (int argc, char **argv)
goto error;
}
+ if (chdir ("/") == -1)
+ goto error;
+
j = 0;
nargv[j++] = PYTHON;
- nargv[j++] = GSYNCD_PREFIX"/python/syncdaemon/gsyncd.py";
+ nargv[j++] = GSYNCD_PREFIX"/python/syncdaemon/"GSYNCD_PY;
for (i = 1; i < argc; i++)
nargv[j++] = argv[i];
if (config_file[0]) {
@@ -149,10 +154,72 @@ invoke_gsyncd (int argc, char **argv)
return 1;
}
+
+static int
+find_gsyncd (pid_t pid, pid_t ppid, char *name, void *data)
+{
+ char buf[NAME_MAX * 2] = {0,};
+ char *p = NULL;
+ int zeros = 0;
+ int ret = 0;
+ int fd = -1;
+ pid_t *pida = (pid_t *)data;
+
+ if (ppid != pida[0])
+ return 0;
+
+ ret = gf_asprintf (&p, PROC"/%d/cmdline", pid);
+ if (ret == -1) {
+ fprintf (stderr, "out of memory\n");
+ return -1;
+ }
+
+ fd = open (p, O_RDONLY);
+ if (fd == -1)
+ return 0;
+ ret = read (fd, buf, sizeof (buf));
+ close (fd);
+ if (ret == -1)
+ return 0;
+ for (zeros = 0, p = buf; zeros < 2 && p < buf + ret; p++)
+ zeros += !*p;
+
+ ret = 0;
+ switch (zeros) {
+ case 2:
+ if ((strcmp (basename (buf), basename (PYTHON)) ||
+ strcmp (basename (buf + strlen (buf) + 1), GSYNCD_PY)) == 0) {
+ ret = 1;
+ break;
+ }
+ /* fallthrough */
+ case 1:
+ if (strcmp (basename (buf), GSYNCD_PY) == 0)
+ ret = 1;
+ }
+
+ if (ret == 1) {
+ if (pida[1] != -1) {
+ fprintf (stderr, GSYNCD_PY" sibling is not unique");
+ return -1;
+ }
+ pida[1] = pid;
+ }
+
+ return 0;
+}
+
static int
invoke_rsync (int argc, char **argv)
{
- int i = 0;
+ int i = 0;
+ char *p = NULL;
+ pid_t pid = -1;
+ pid_t ppid = -1;
+ pid_t pida[] = {-1, -1};
+ char *name = NULL;
+ char buf[PATH_MAX + 1] = {0,};
+ int ret = 0;
assert (argv[argc] == NULL);
@@ -161,24 +228,42 @@ invoke_rsync (int argc, char **argv)
for (i = 2; i < argc && argv[i][0] == '-'; i++);
- if (!(i == argc ||
- (i == argc - 2 && strcmp (argv[i], ".") == 0 && argv[i + 1][0] == '/')))
+ if (!(i == argc - 2 && strcmp (argv[i], ".") == 0 && argv[i + 1][0] == '/')) {
+ fprintf (stderr, "need an rsync invocation without protected args\n");
goto error;
+ }
- /* XXX a proper check would involve the following:
- * - require rsync to not protect args (ie. pass target in command line)
- * - find out proper synchronization target by:
- * - looking up sshd process we origin from
- * - within its children, find the gsyncd process
- * that maintains the aux mount
- * - find out mount directory by checking the working directory
- * of the gsyncd process
- * - demand that rsync target equals to sync target
- *
- * As of now, what we implement is dispatching rsync invocation to
- * our system rsync, that handles the cardinal issue of controlling
- * remote-requested command invocations.
- */
+ /* look up sshd we are spawned from */
+ for (pid = getpid () ;; pid = ppid) {
+ ppid = pidinfo (pid, &name);
+ if (ppid < 0) {
+ fprintf (stderr, "sshd ancestor not found\n");
+ goto error;
+ }
+ if (strcmp (name, "sshd") == 0)
+ break;
+ }
+ /* look up "ssh-sibling" gsyncd */
+ pida[0] = pid;
+ ret = prociter (find_gsyncd, pida);
+ if (ret == -1 || pida[1] == -1) {
+ fprintf (stderr, "gsyncd sibling not found\n");
+ goto error;
+ }
+ /* check if rsync target matches gsyncd target */
+ if (gf_asprintf (&p, PROC"/%d/cwd", pida[1]) == -1) {
+ fprintf (stderr, "out of memory\n");
+ goto error;
+ }
+ ret = readlink (p, buf, sizeof (buf));
+ if (ret == -1 || ret == sizeof (buf))
+ goto error;
+ if (strcmp (argv[argc - 1], "/") == 0 /* root dir cannot be a target */ ||
+ (strcmp (argv[argc - 1], p) /* match against gluster target */ &&
+ strcmp (argv[argc - 1], buf) /* match against file target */) != 0) {
+ fprintf (stderr, "rsync target does not match "GEOREP" session\n");
+ goto error;
+ }
argv[0] = RSYNC;
@@ -192,6 +277,7 @@ invoke_rsync (int argc, char **argv)
return 1;
}
+
struct invocable {
char *name;
int (*invoker) (int argc, char **argv);
diff --git a/xlators/features/marker/utils/src/procdiggy.c b/xlators/features/marker/utils/src/procdiggy.c
new file mode 100644
index 000000000..fc0f97999
--- /dev/null
+++ b/xlators/features/marker/utils/src/procdiggy.c
@@ -0,0 +1,124 @@
+/*
+ Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "common-utils.h"
+#include "procdiggy.h"
+
+pid_t
+pidinfo (pid_t pid, char **name)
+{
+ char buf[NAME_MAX * 2] = {0,};
+ FILE *f = NULL;
+ char *p = NULL;
+ int ret = 0;
+
+ ret = gf_asprintf (&p, PROC"/%d/status", pid);
+ if (ret == -1)
+ goto oom;
+
+ f = fopen (p, "r");
+ if (!f)
+ return -1;
+
+ if (name)
+ *name = NULL;
+ for (;;) {
+ memset (buf, 0, sizeof (buf));
+ if (fgets (buf, sizeof (buf), f) == NULL ||
+ buf[strlen (buf) - 1] != '\n') {
+ pid = -1;
+ goto out;
+ }
+ buf[strlen (buf) -1] = '\0';
+
+ if (name && !*name) {
+ p = strtail (buf, "Name:");
+ if (p) {
+ while (isspace (*++p));
+ *name = gf_strdup (p);
+ if (!*name)
+ goto oom;
+ continue;
+ }
+ }
+
+ p = strtail (buf, "PPid:");
+ if (p)
+ break;
+ }
+
+ while (isspace (*++p));
+ ret = gf_string2int (p, &pid);
+ if (ret == -1)
+ pid = -1;
+
+ out:
+ fclose (f);
+ return pid;
+
+ oom:
+ fclose (f);
+ fprintf (stderr, "out of memory\n");
+ return -2;
+}
+
+int
+prociter (int (*proch) (pid_t pid, pid_t ppid, char *name, void *data),
+ void *data)
+{
+ char *name = NULL;
+ DIR *d = NULL;
+ struct dirent *de = NULL;
+ pid_t pid = -1;
+ pid_t ppid = -1;
+ int ret = 0;
+
+ d = opendir (PROC);
+ while (errno = 0, de = readdir (d)) {
+ if (gf_string2int (de->d_name, &pid) != -1 && pid >= 0) {
+ ppid = pidinfo (pid, &name);
+ switch (ppid) {
+ case -1: continue;
+ case -2: return -1;
+ }
+ ret = proch (pid, ppid, name, data);
+ if (ret)
+ return ret;
+ }
+ }
+ if (errno) {
+ fprintf (stderr, "failed to traverse "PROC" (%s)\n",
+ strerror (errno));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/xlators/features/marker/utils/src/procdiggy.h b/xlators/features/marker/utils/src/procdiggy.h
new file mode 100644
index 000000000..f4586de6c
--- /dev/null
+++ b/xlators/features/marker/utils/src/procdiggy.h
@@ -0,0 +1,26 @@
+/*
+ Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#define PROC "/proc"
+
+pid_t pidinfo (pid_t pid, char **name);
+
+int prociter (int (*proch) (pid_t pid, pid_t ppid, char *name, void *data),
+ void *data);
+
diff --git a/xlators/features/marker/utils/syncdaemon/gsyncd.py b/xlators/features/marker/utils/syncdaemon/gsyncd.py
index 6747acbce..9771822dc 100644
--- a/xlators/features/marker/utils/syncdaemon/gsyncd.py
+++ b/xlators/features/marker/utils/syncdaemon/gsyncd.py
@@ -155,7 +155,7 @@ def main_i():
op.add_option('--session-owner', metavar='ID')
op.add_option('-s', '--ssh-command', metavar='CMD', default='ssh')
op.add_option('--rsync-command', metavar='CMD', default='rsync')
- op.add_option('--rsync-extra', metavar='ARGS', default='-sS', help=SUPPRESS_HELP)
+ op.add_option('--rsync-extra', metavar='ARGS', default='-S', help=SUPPRESS_HELP)
op.add_option('--timeout', metavar='SEC', type=int, default=120)
op.add_option('--sync-jobs', metavar='N', type=int, default=3)
op.add_option('--turns', metavar='N', type=int, default=0, help=SUPPRESS_HELP)