diff options
author | Csaba Henk <csaba@gluster.com> | 2011-09-13 13:12:38 +0200 |
---|---|---|
committer | Vijay Bellur <vijay@gluster.com> | 2011-09-22 05:23:54 -0700 |
commit | 7e04913aa6f4ddb45e95099ef648564bf90da0b3 (patch) | |
tree | c456a74980b0dcc7eaa6338ee46454a55bf16156 /xlators/features/marker/utils/src/gsyncd.c | |
parent | 2ab00369e7ef99d287dad5301d2f334dcfd67a70 (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>
Diffstat (limited to 'xlators/features/marker/utils/src/gsyncd.c')
-rw-r--r-- | xlators/features/marker/utils/src/gsyncd.c | 122 |
1 files changed, 104 insertions, 18 deletions
diff --git a/xlators/features/marker/utils/src/gsyncd.c b/xlators/features/marker/utils/src/gsyncd.c index cebca1aeaae..d3fa2d325a6 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); |