use fixed path to cgroup-network-helper.sh; strictier path checking; fixes #3269
Costa Tsaousis (ktsaou) committed
Jan 13, 2018 at 04:59 UTC
a994127896503647cc96a2bbe58faed5fa51dbc8
2 files changed
+37
-40
plugins.d/cgroup-network-helper.sh
-6
@@ -69,12 +69,6 @@ debug() {
69
[ $(( ${BASH_VERSINFO[0]} )) -lt 4 ] && \
70
fatal "BASH version 4 or later is required (this is ${BASH_VERSION})."
71
72
-# -----------------------------------------------------------------------------
73
-# defaults to allow running this script by hand
74
-
75
-[ -z "${NETDATA_PLUGINS_DIR}" ] && NETDATA_PLUGINS_DIR="$(dirname "${0}")"
76
-[ -z "${NETDATA_CONFIG_DIR}" ] && NETDATA_CONFIG_DIR="$(dirname "${0}")/../../../../etc/netdata"
77
-
72
# -----------------------------------------------------------------------------
73
# parse the arguments
74
src/cgroup-network.c
+37
-34
@@ -9,17 +9,11 @@
9
#endif
10
11
char *host_prefix = "";
12
-char *pluginsdir = "";
13
-char *configdir = "";
12
13
char environment_variable2[FILENAME_MAX + 50] = "";
16
-char environment_variable3[FILENAME_MAX + 50] = "";
17
-char environment_variable4[FILENAME_MAX + 50] = "";
14
char *environment[] = {
15
"PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",
16
environment_variable2,
21
- environment_variable3,
22
- environment_variable4,
17
NULL
18
};
19
@@ -452,9 +446,9 @@ void call_the_helper(pid_t pid, const char *cgroup) {
446
447
char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
448
if(cgroup)
455
- snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec %s/cgroup-network-helper.sh --cgroup '%s'", pluginsdir, cgroup);
449
+ snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --cgroup '%s'", cgroup);
450
else
457
- snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec %s/cgroup-network-helper.sh --pid %d", pluginsdir, pid);
451
+ snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --pid %d", pid);
452
453
info("running: %s", buffer);
454
@@ -484,18 +478,49 @@ void call_the_helper(pid_t pid, const char *cgroup) {
478
error("cannot execute cgroup-network helper script: %s", buffer);
479
}
480
481
+int is_valid_path_symbol(char c) {
482
+ switch(c) {
483
+ case '/': // path separators
484
+ case '\\': // needed for virsh domains \x2d1\x2dname
485
+ case ' ': // space
486
+ case '-': // hyphen
487
+ case '_': // underscore
488
+ case '.': // dot
489
+ case ',': // comma
490
+ return 1;
491
+
492
+ default:
493
+ return 0;
494
+ }
495
+}
496
+
497
+// we will pass this path a shell script running as root
498
+// so, we need to make sure the path will be valid
499
+// and will not include anything that could allow
500
+// the caller use shell expansion for gaining escalated
501
+// privileges.
502
int verify_path(const char *path) {
503
struct stat sb;
504
505
char c;
506
const char *s = path;
507
while((c = *s++)) {
493
- if(c == '$' || c == '`' || c == '<' || c == '>') {
508
+ if(!( isalnum(c) || is_valid_path_symbol(c) )) {
509
error("invalid character in path '%s'", path);
510
return -1;
511
}
512
}
513
514
+ if(strstr(path, "\\") && !strstr(path, "\\x")) {
515
+ error("invalid escape sequence in path '%s'", path);
516
+ return 1;
517
+ }
518
+
519
+ if(strstr(path, "/../")) {
520
+ error("invalid parent path sequence detected in '%s'", path);
521
+ return 1;
522
+ }
523
+
524
if(path[0] != '/') {
525
error("only absolute path names are supported - invalid path '%s'", path);
526
return -1;
@@ -572,35 +597,13 @@ int main(int argc, char **argv) {
597
host_prefix = "";
598
599
if(host_prefix[0] != '\0' && verify_path(host_prefix) == -1)
575
- fatal("cannot find path NETDATA_HOST_PREFIX '%s'", host_prefix);
576
-
577
- // ------------------------------------------------------------------------
578
- // make sure NETDATA_CONFIG_DIR is safe
579
-
580
- configdir = getenv("NETDATA_CONFIG_DIR");
581
- if(!configdir || !*configdir) {
582
- configdir = "";
583
- }
584
- else if(verify_path(configdir) == -1)
585
- fatal("cannot find path NETDATA_CONFIG_DIR '%s'", configdir);
586
-
587
- // ------------------------------------------------------------------------
588
- // make sure NETDATA_PLUGINS_DIR is safe
589
-
590
- pluginsdir = getenv("NETDATA_PLUGINS_DIR");
591
- if(!pluginsdir || !*pluginsdir) {
592
- char *me = strdupz(argv[0]);
593
- pluginsdir = dirname(me);
594
- }
595
- else if(verify_path(pluginsdir) == -1)
596
- fatal("cannot find path NETDATA_PLUGINS_DIR '%s'", pluginsdir);
600
+ fatal("invalid NETDATA_HOST_PREFIX '%s'", host_prefix);
601
602
// ------------------------------------------------------------------------
603
// build a safe environment for our script
604
605
+ // the first environment variable is a fixed PATH=
606
snprintfz(environment_variable2, sizeof(environment_variable2) - 1, "NETDATA_HOST_PREFIX=%s", host_prefix);
602
- snprintfz(environment_variable3, sizeof(environment_variable3) - 1, "NETDATA_PLUGINS_DIR=%s", pluginsdir);
603
- snprintfz(environment_variable4, sizeof(environment_variable4) - 1, "NETDATA_CONFIG_DIR=%s", configdir);
607
608
// ------------------------------------------------------------------------
609
@@ -626,7 +629,7 @@ int main(int argc, char **argv) {
629
else if(!strcmp(argv[1], "--cgroup")) {
630
char *cgroup = argv[2];
631
if(verify_path(cgroup) == -1)
629
- fatal("cgroup '%s' does not exist.", cgroup);
632
+ fatal("cgroup '%s' does not exist or is not valid.", cgroup);
633
634
pid = read_pid_from_cgroup(cgroup);
635
call_the_helper(pid, cgroup);