@cryptotaxi247 / netdata-1 / commits / 555fa18cd

strip environment on cgroup-network; fixes #3269

Costa Tsaousis (ktsaou) committed Jan 11, 2018 at 21:03 UTC 555fa18cd10f079dffb726b54f590c614ef16ad7
4 files changed +138 -17
plugins.d/cgroup-network-helper.sh
+4 -2
@@ -22,7 +22,10 @@
22
23 # -----------------------------------------------------------------------------
24
25 -export PATH="${PATH}:/sbin:/usr/sbin:/usr/local/sbin"
25 +# the system path is cleared by cgroup-network
26 +export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
27 +[ -x /etc/profile ] && source /etc/profile
28 +
29 export LC_ALL=C
30
31 PROGRAM_NAME="$(basename "${0}")"
@@ -72,7 +75,6 @@ debug() {
75
76 [ -z "${NETDATA_PLUGINS_DIR}" ] && NETDATA_PLUGINS_DIR="$(dirname "${0}")"
77 [ -z "${NETDATA_CONFIG_DIR}" ] && NETDATA_CONFIG_DIR="$(dirname "${0}")/../../../../etc/netdata"
75 -[ -z "${NETDATA_CACHE_DIR}" ] && NETDATA_CACHE_DIR="$(dirname "${0}")/../../../../var/cache/netdata"
78
79 # -----------------------------------------------------------------------------
80 # parse the arguments
src/cgroup-network.c
+97 -15
@@ -8,6 +8,20 @@
8 #include <sched.h>
9 #endif
10
11 +char *host_prefix = "";
12 +char *pluginsdir = "";
13 +char *configdir = "";
14 +
15 +char environment_variable1[FILENAME_MAX + 1] = "";
16 +char environment_variable2[FILENAME_MAX + 1] = "";
17 +char environment_variable3[FILENAME_MAX + 1] = "";
18 +char *environment[] = {
19 + environment_variable1,
20 + environment_variable2,
21 + environment_variable3,
22 + NULL
23 +};
24 +
25 // ----------------------------------------------------------------------------
26 // callback required by fatal()
27
@@ -18,6 +32,8 @@ void health_reload(void) {};
32 void rrdhost_save_all(void) {};
33
34
35 +// ----------------------------------------------------------------------------
36 +
37 struct iface {
38 const char *device;
39 uint32_t hash;
@@ -428,15 +444,7 @@ cleanup:
444 // call the external helper
445
446 #define CGROUP_NETWORK_INTERFACE_MAX_LINE 2048
431 -void call_the_helper(const char *me, pid_t pid, const char *cgroup) {
432 - const char *pluginsdir = getenv("NETDATA_PLUGINS_DIR");
433 - char *m = NULL;
434 -
435 - if(!pluginsdir || !*pluginsdir) {
436 - m = strdupz(me);
437 - pluginsdir = dirname(m);
438 - }
439 -
447 +void call_the_helper(pid_t pid, const char *cgroup) {
448 if(setresuid(0, 0, 0) == -1)
449 error("setresuid(0, 0, 0) failed.");
450
@@ -449,7 +457,7 @@ void call_the_helper(const char *me, pid_t pid, const char *cgroup) {
457 info("running: %s", buffer);
458
459 pid_t cgroup_pid;
452 - FILE *fp = mypopen(buffer, &cgroup_pid);
460 + FILE *fp = mypopene(buffer, &cgroup_pid, environment);
461 if(fp) {
462 char *s;
463 while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) {
@@ -472,8 +480,36 @@ void call_the_helper(const char *me, pid_t pid, const char *cgroup) {
480 }
481 else
482 error("cannot execute cgroup-network helper script: %s", buffer);
483 +}
484
476 - freez(m);
485 +int verify_path(const char *path) {
486 + struct stat sb;
487 +
488 + char c;
489 + const char *s = path;
490 + while((c = *s++)) {
491 + if(c == '$' || c == '`') {
492 + error("invalid character in path '%s'", path);
493 + return -1;
494 + }
495 + }
496 +
497 + if(path[0] != '/') {
498 + error("only absolute path names are supported - invalid path '%s'", path);
499 + return -1;
500 + }
501 +
502 + if (stat(path, &sb) == -1) {
503 + error("cannot stat() path '%s'", path);
504 + return -1;
505 + }
506 +
507 + if((sb.st_mode & S_IFMT) != S_IFDIR) {
508 + error("path '%s' is not a directory", path);
509 + return -1;
510 + }
511 +
512 + return 0;
513 }
514
515
@@ -492,6 +528,47 @@ int main(int argc, char **argv) {
528 program_version = VERSION;
529 error_log_syslog = 0;
530
531 +
532 + // ------------------------------------------------------------------------
533 + // make sure NETDATA_HOST_PREFIX is safe
534 +
535 + host_prefix = getenv("NETDATA_HOST_PREFIX");
536 + if(!host_prefix || !*host_prefix)
537 + host_prefix = "";
538 +
539 + if(host_prefix[0] != '\0' && verify_path(host_prefix) == -1)
540 + fatal("cannot find path NETDATA_HOST_PREFIX '%s'", host_prefix);
541 +
542 + // ------------------------------------------------------------------------
543 + // make sure NETDATA_CONFIG_DIR is safe
544 +
545 + configdir = getenv("NETDATA_CONFIG_DIR");
546 + if(!configdir || !*configdir) {
547 + configdir = "";
548 + }
549 + else if(verify_path(configdir) == -1)
550 + fatal("cannot find path NETDATA_CONFIG_DIR '%s'", configdir);
551 +
552 + // ------------------------------------------------------------------------
553 + // make sure NETDATA_PLUGINS_DIR is safe
554 +
555 + pluginsdir = getenv("NETDATA_PLUGINS_DIR");
556 + if(!pluginsdir || !*pluginsdir) {
557 + char *me = strdupz(argv[0]);
558 + pluginsdir = dirname(me);
559 + }
560 + else if(verify_path(pluginsdir) == -1)
561 + fatal("cannot find path NETDATA_PLUGINS_DIR '%s'", pluginsdir);
562 +
563 + // ------------------------------------------------------------------------
564 + // build a safe environment for our script
565 +
566 + snprintfz(environment_variable1, FILENAME_MAX, "NETDATA_HOST_PREFIX=%s", host_prefix);
567 + snprintfz(environment_variable2, FILENAME_MAX, "NETDATA_PLUGINS_DIR=%s", pluginsdir);
568 + snprintfz(environment_variable3, FILENAME_MAX, "NETDATA_CONFIG_DIR=%s", configdir);
569 +
570 + // ------------------------------------------------------------------------
571 +
572 if(argc == 2 && (!strcmp(argv[1], "version") || !strcmp(argv[1], "-version") || !strcmp(argv[1], "--version") || !strcmp(argv[1], "-v") || !strcmp(argv[1], "-V"))) {
573 fprintf(stderr, "cgroup-network %s\n", VERSION);
574 exit(0);
@@ -509,15 +586,20 @@ int main(int argc, char **argv) {
586 return 2;
587 }
588
512 - call_the_helper(argv[0], pid, NULL);
589 + call_the_helper(pid, NULL);
590 }
591 else if(!strcmp(argv[1], "--cgroup")) {
515 - pid = read_pid_from_cgroup(argv[2]);
516 - call_the_helper(argv[0], pid, argv[2]);
592 + char pathname[FILENAME_MAX + 1];
593 + snprintfz(pathname, FILENAME_MAX, "%s%s", host_prefix, argv[2]);
594 + if(verify_path(pathname) == -1)
595 + fatal("cgroup '%s' does not exist.", pathname);
596 +
597 + pid = read_pid_from_cgroup(pathname);
598 + call_the_helper(pid, pathname);
599
600 if(pid <= 0 && !detected_devices) {
601 errno = 0;
520 - error("Cannot find a cgroup PID from cgroup '%s'", argv[2]);
602 + error("Cannot find a cgroup PID from cgroup '%s'", pathname);
603 }
604 }
605 else
src/popen.c
+36
@@ -113,6 +113,42 @@ FILE *mypopen(const char *command, volatile pid_t *pidptr)
113 exit(1);
114 }
115
116 +FILE *mypopene(const char *command, volatile pid_t *pidptr, char **env) {
117 + int pipefd[2];
118 +
119 + if(pipe(pipefd) == -1)
120 + return NULL;
121 +
122 + int pid = fork();
123 + if(pid == -1) {
124 + close(pipefd[PIPE_READ]);
125 + close(pipefd[PIPE_WRITE]);
126 + return NULL;
127 + }
128 + if(pid != 0) {
129 + // the parent
130 + *pidptr = pid;
131 + close(pipefd[PIPE_WRITE]);
132 + FILE *fp = fdopen(pipefd[PIPE_READ], "r");
133 + return(fp);
134 + }
135 + // the child
136 +
137 + // close all files
138 + int i;
139 + for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--)
140 + if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i);
141 +
142 + // move the pipe to stdout
143 + if(pipefd[PIPE_WRITE] != STDOUT_FILENO) {
144 + dup2(pipefd[PIPE_WRITE], STDOUT_FILENO);
145 + close(pipefd[PIPE_WRITE]);
146 + }
147 +
148 + execle("/bin/sh", "sh", "-c", command, NULL, env);
149 + exit(1);
150 +}
151 +
152 int mypclose(FILE *fp, pid_t pid) {
153 debug(D_EXIT, "Request to mypclose() on pid %d", pid);
154
src/popen.h
+1
@@ -5,6 +5,7 @@
5 #define PIPE_WRITE 1
6
7 extern FILE *mypopen(const char *command, volatile pid_t *pidptr);
8 +extern FILE *mypopene(const char *command, volatile pid_t *pidptr, char **env);
9 extern int mypclose(FILE *fp, pid_t pid);
10
11 #endif /* NETDATA_POPEN_H */