diff options
| -rw-r--r-- | xlators/features/marker/utils/src/Makefile.am | 4 | ||||
| -rw-r--r-- | xlators/features/marker/utils/src/gsyncd.c | 122 | ||||
| -rw-r--r-- | xlators/features/marker/utils/src/procdiggy.c | 124 | ||||
| -rw-r--r-- | xlators/features/marker/utils/src/procdiggy.h | 26 | ||||
| -rw-r--r-- | xlators/features/marker/utils/syncdaemon/gsyncd.py | 2 | 
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 74e2b3ef516..73c99cb76d8 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 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); diff --git a/xlators/features/marker/utils/src/procdiggy.c b/xlators/features/marker/utils/src/procdiggy.c new file mode 100644 index 00000000000..fc0f97999d6 --- /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 00000000000..f4586de6c67 --- /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 6747acbce6f..9771822dcea 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)  | 
