int prociter(int (*proch)(pid_t pid, pid_t ppid, char *tmpname, void *data), void *data) { char *name = NULL; DIR *d = NULL; struct dirent *de = NULL; struct dirent scratch[2] = { { 0, }, }; pid_t pid = -1; pid_t ppid = -1; int ret = 0; d = sys_opendir(PROC); if (!d) return -1; for (;;) { errno = 0; de = sys_readdir(d, scratch); if (!de || errno != 0) break; if (gf_string2int(de->d_name, &pid) != -1 && pid >= 0) { ppid = pidinfo(pid, &name); switch (ppid) { case -1: continue; case -2: break; } ret = proch(pid, ppid, name, data); GF_FREE(name); if (ret) break; } } sys_closedir(d); if (!de && errno) { fprintf(stderr, "failed to traverse " PROC " (%s)\n", strerror(errno)); ret = -1; } return ret; }
int prociter (int (*proch) (pid_t pid, pid_t ppid, char *tmpname, 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); if (!d) { ret = -1; goto out; } 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: closedir (d); return -1; } ret = proch (pid, ppid, name, data); if (ret) { goto out; } GF_FREE (name); name = NULL; } } if (errno) { fprintf (stderr, "failed to traverse "PROC" (%s)\n", strerror (errno)); goto out; } ret = 0; out: if (d) closedir (d); if (name) GF_FREE (name); return ret; }
static int invoke_rsync (int argc, char **argv) { int i = 0; char path[PATH_MAX] = {0,}; 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); if (argc < 2 || strcmp (argv[1], "--server") != 0) goto error; for (i = 2; i < argc && argv[i][0] == '-'; i++); if (!(i == argc - 2 && strcmp (argv[i], ".") == 0 && argv[i + 1][0] == '/')) { fprintf (stderr, "need an rsync invocation without protected args\n"); goto error; } /* 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) { GF_FREE (name); break; } GF_FREE (name); } /* 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 */ sprintf (path, PROC"/%d/cwd", pida[1]); ret = readlink (path, 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], path) /* 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; execvp (RSYNC, argv); fprintf (stderr, "exec of "RSYNC" failed\n"); return 127; error: fprintf (stderr, "disallowed "RSYNC" invocation\n"); return 1; }