@cryptotaxi247 / netdata-1 / commits / d17f6869e

more security fixes by Synacktiv

Costa Tsaousis (ktsaou) committed Apr 18, 2018 at 23:10 UTC d17f6869ee8542c54d4c2280203676fb7b229001
7 files changed +85 -28
src/apps_plugin.c
+9 -17
@@ -856,7 +856,7 @@ static inline int read_proc_pid_cmdline(struct pid_stat *p) {
856 p->cmdline_filename = strdupz(filename);
857 }
858
859 - int fd = open(p->cmdline_filename, O_RDONLY, 0666);
859 + int fd = open(p->cmdline_filename, procfile_open_flags, 0666);
860 if(unlikely(fd == -1)) goto cleanup;
861
862 ssize_t i, bytes = read(fd, cmdline, MAX_CMDLINE);
@@ -3314,7 +3314,6 @@ cleanup:
3314 static void parse_args(int argc, char **argv)
3315 {
3316 int i, freq = 0;
3317 - char *name = NULL;
3317
3318 for(i = 1; i < argc; i++) {
3319 if(!freq) {
@@ -3428,20 +3427,14 @@ static void parse_args(int argc, char **argv)
3427 exit(1);
3428 }
3429
3431 - if(!name) {
3432 - name = argv[i];
3433 - continue;
3434 - }
3435 -
3430 error("Cannot understand option %s", argv[i]);
3431 exit(1);
3432 }
3433
3434 if(freq > 0) update_every = freq;
3441 - if(!name || !*name) name = "groups";
3435
3443 - if(read_apps_groups_conf(name)) {
3444 - error("Cannot read process groups '%s/apps_%s.conf'. There are no internal defaults. Failing.", config_dir, name);
3436 + if(read_apps_groups_conf("groups")) {
3437 + error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", config_dir);
3438 exit(1);
3439 }
3440 }
@@ -3523,12 +3516,11 @@ int main(int argc, char **argv) {
3516 error_log_errors_per_period = 100;
3517 error_log_throttle_period = 3600;
3518
3519 + // since apps.plugin runs as root, prevent it from opening symbolic links
3520 + procfile_open_flags = O_RDONLY|O_NOFOLLOW;
3521 +
3522 netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
3527 - if(netdata_configured_host_prefix == NULL) {
3528 - // info("NETDATA_HOST_PREFIX is not passed from netdata");
3529 - netdata_configured_host_prefix = "";
3530 - }
3531 - // else info("Found NETDATA_HOST_PREFIX='%s'", netdata_configured_host_prefix);
3523 + if(verify_netdata_host_prefix() == -1) exit(1);
3524
3525 config_dir = getenv("NETDATA_CONFIG_DIR");
3526 if(config_dir == NULL) {
@@ -3563,14 +3555,14 @@ int main(int argc, char **argv) {
3555 error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
3556 "Without these, apps.plugin cannot report disk I/O utilization of other processes. "
3557 "To enable capabilities run: sudo setcap cap_dac_read_search,cap_sys_ptrace+ep %s; "
3566 - "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; "
3558 + "To enable setuid to root run: sudo chown root:netdata %s; sudo chmod 4750 %s; "
3559 , uid, euid, argv[0], argv[0], argv[0]
3560 );
3561 #else
3562 error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
3563 "Without these, apps.plugin cannot report disk I/O utilization of other processes. "
3564 "Your system does not support capabilities. "
3573 - "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; "
3565 + "To enable setuid to root run: sudo chown root:netdata %s; sudo chmod 4750 %s; "
3566 , uid, euid, argv[0], argv[0]
3567 );
3568 #endif
src/cgroup-network.c
+5 -8
@@ -8,8 +8,6 @@
8 #include <sched.h>
9 #endif
10
11 -char *host_prefix = "";
12 -
11 char environment_variable2[FILENAME_MAX + 50] = "";
12 char *environment[] = {
13 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",
@@ -592,18 +590,17 @@ int main(int argc, char **argv) {
590 // ------------------------------------------------------------------------
591 // make sure NETDATA_HOST_PREFIX is safe
592
595 - host_prefix = getenv("NETDATA_HOST_PREFIX");
596 - if(!host_prefix || !*host_prefix)
597 - host_prefix = "";
593 + netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
594 + if(verify_netdata_host_prefix() == -1) exit(1);
595
599 - if(host_prefix[0] != '\0' && verify_path(host_prefix) == -1)
600 - fatal("invalid NETDATA_HOST_PREFIX '%s'", host_prefix);
596 + if(netdata_configured_host_prefix[0] != '\0' && verify_path(netdata_configured_host_prefix) == -1)
597 + fatal("invalid NETDATA_HOST_PREFIX '%s'", netdata_configured_host_prefix);
598
599 // ------------------------------------------------------------------------
600 // build a safe environment for our script
601
602 // the first environment variable is a fixed PATH=
606 - snprintfz(environment_variable2, sizeof(environment_variable2) - 1, "NETDATA_HOST_PREFIX=%s", host_prefix);
603 + snprintfz(environment_variable2, sizeof(environment_variable2) - 1, "NETDATA_HOST_PREFIX=%s", netdata_configured_host_prefix);
604
605 // ------------------------------------------------------------------------
606
src/common.c
+61
@@ -1359,3 +1359,64 @@ int recursively_delete_dir(const char *path, const char *reason) {
1359
1360 return ret;
1361 }
1362 +
1363 +static int is_virtual_filesystem(const char *path, char **reason) {
1364 + struct statfs stat;
1365 + // stat.f_fsid.__val[0] is a file system id
1366 + // stat.f_fsid.__val[1] is the inode
1367 + // so their combination uniquely identifies the file/dir
1368 +
1369 + if (statfs(path, &stat) == -1) {
1370 + if(reason) *reason = "failed to statfs()";
1371 + return -1;
1372 + }
1373 +
1374 + if(stat.f_fsid.__val[0] != 0 || stat.f_fsid.__val[1] != 0) {
1375 + errno = EINVAL;
1376 + if(reason) *reason = "is not a virtual file system";
1377 + return -1;
1378 + }
1379 +
1380 + return 0;
1381 +}
1382 +
1383 +int verify_netdata_host_prefix() {
1384 + if(!netdata_configured_host_prefix)
1385 + netdata_configured_host_prefix = "";
1386 +
1387 + if(!*netdata_configured_host_prefix)
1388 + return 0;
1389 +
1390 + char buffer[FILENAME_MAX + 1];
1391 + char *path = netdata_configured_host_prefix;
1392 + char *reason = "unknown reason";
1393 + errno = 0;
1394 +
1395 + struct stat sb;
1396 + if (stat(path, &sb) == -1) {
1397 + reason = "failed to stat()";
1398 + goto failed;
1399 + }
1400 +
1401 + if((sb.st_mode & S_IFMT) != S_IFDIR) {
1402 + errno = EINVAL;
1403 + reason = "is not a directory";
1404 + goto failed;
1405 + }
1406 +
1407 + path = buffer;
1408 + snprintfz(path, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix);
1409 + if(is_virtual_filesystem(path, &reason) == -1)
1410 + goto failed;
1411 +
1412 + snprintfz(path, FILENAME_MAX, "%s/sys", netdata_configured_host_prefix);
1413 + if(is_virtual_filesystem(path, &reason) == -1)
1414 + goto failed;
1415 +
1416 + return 0;
1417 +
1418 +failed:
1419 + error("Ignoring host prefix '%s': path '%s' %s", netdata_configured_host_prefix, path, reason);
1420 + netdata_configured_host_prefix = "";
1421 + return -1;
1422 +}
src/common.h
+2 -1
@@ -5,7 +5,6 @@
5 #include <config.h>
6 #endif
7
8 -
8 // ----------------------------------------------------------------------------
9 // system include files for all netdata C programs
10
@@ -76,6 +75,7 @@
75 #include <sys/resource.h>
76 #include <sys/socket.h>
77 #include <sys/stat.h>
78 +#include <sys/vfs.h>
79 #include <sys/statvfs.h>
80 #include <sys/syscall.h>
81 #include <sys/time.h>
@@ -333,6 +333,7 @@ extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len);
333
334 extern int processors;
335 extern long get_system_cpus(void);
336 +extern int verify_netdata_host_prefix();
337
338 extern pid_t pid_max;
339 extern pid_t get_system_pid_max(void);
src/main.c
+1
@@ -480,6 +480,7 @@ static void get_netdata_configured_variables() {
480 // ------------------------------------------------------------------------
481
482 netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", "");
483 + verify_netdata_host_prefix();
484
485 // --------------------------------------------------------------------
486 // get KSM settings
src/procfile.c
+4 -2
@@ -7,6 +7,8 @@
7 #define PFLINES_INCREASE_STEP 10
8 #define PROCFILE_INCREMENT_BUFFER 512
9
10 +int procfile_open_flags = O_RDONLY;
11 +
12 int procfile_adaptive_initial_allocation = 0;
13
14 // if adaptive allocation is set, these store the
@@ -391,7 +393,7 @@ void procfile_set_open_close(procfile *ff, const char *open, const char *close)
393 procfile *procfile_open(const char *filename, const char *separators, uint32_t flags) {
394 debug(D_PROCFILE, PF_PREFIX ": Opening file '%s'", filename);
395
394 - int fd = open(filename, O_RDONLY, 0666);
396 + int fd = open(filename, procfile_open_flags, 0666);
397 if(unlikely(fd == -1)) {
398 if(unlikely(!(flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot open file '%s'", filename);
399 return NULL;
@@ -427,7 +429,7 @@ procfile *procfile_reopen(procfile *ff, const char *filename, const char *separa
429 close(ff->fd);
430 }
431
430 - ff->fd = open(filename, O_RDONLY, 0666);
432 + ff->fd = open(filename, procfile_open_flags, 0666);
433 if(unlikely(ff->fd == -1)) {
434 procfile_close(ff);
435 return NULL;
src/procfile.h
+3
@@ -103,6 +103,9 @@ extern char *procfile_filename(procfile *ff);
103
104 // ----------------------------------------------------------------------------
105
106 +// set to the O_XXXX flags, to have procfile_open and procfile_reopen use them when opening proc files
107 +extern int procfile_open_flags;
108 +
109 // set this to 1, to have procfile adapt its initial buffer allocation to the max allocation used so far
110 extern int procfile_adaptive_initial_allocation;
111