diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2018-11-07 12:19:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2018-11-07 12:20:17 +0000 |
commit | a64a253794ac64cb40befee54db53bde17dd0d49 (patch) | |
tree | c1024acc5f6e508814b944d99f112259bb28b1be /collectors/cgroups.plugin/cgroup-network.c | |
parent | New upstream version 1.10.0+dfsg (diff) | |
download | netdata-upstream/1.11.0+dfsg.tar.xz netdata-upstream/1.11.0+dfsg.zip |
New upstream version 1.11.0+dfsgupstream/1.11.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | collectors/cgroups.plugin/cgroup-network.c (renamed from src/cgroup-network.c) | 97 |
1 files changed, 64 insertions, 33 deletions
diff --git a/src/cgroup-network.c b/collectors/cgroups.plugin/cgroup-network.c index 0e2d5163a..0cf2a2633 100644 --- a/src/cgroup-network.c +++ b/collectors/cgroups.plugin/cgroup-network.c @@ -1,5 +1,6 @@ -#include "common.h" -#include <libgen.h> +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "libnetdata/libnetdata.h" #ifdef HAVE_SETNS #ifndef _GNU_SOURCE @@ -8,8 +9,6 @@ #include <sched.h> #endif -char *host_prefix = ""; - char environment_variable2[FILENAME_MAX + 50] = ""; char *environment[] = { "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin", @@ -19,14 +18,28 @@ char *environment[] = { // ---------------------------------------------------------------------------- -// callback required by fatal() +// callback required by fatal() void netdata_cleanup_and_exit(int ret) { exit(ret); } -void health_reload(void) {}; -void rrdhost_save_all(void) {}; +// callbacks required by popen() +void signals_block(void) {}; +void signals_unblock(void) {}; +void signals_reset(void) {}; + +// callback required by eval() +int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result) { + (void)variable; + (void)hash; + (void)rc; + (void)result; + return 0; +}; + +// required by get_system_cpus() +char *netdata_configured_host_prefix = ""; // ---------------------------------------------------------------------------- @@ -41,8 +54,10 @@ struct iface { }; unsigned int read_iface_iflink(const char *prefix, const char *iface) { + if(!prefix) prefix = ""; + char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/iflink", prefix?prefix:"", iface); + snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/iflink", prefix, iface); unsigned long long iflink = 0; int ret = read_single_number_file(filename, &iflink); @@ -52,8 +67,10 @@ unsigned int read_iface_iflink(const char *prefix, const char *iface) { } unsigned int read_iface_ifindex(const char *prefix, const char *iface) { + if(!prefix) prefix = ""; + char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/ifindex", prefix?prefix:"", iface); + snprintfz(filename, FILENAME_MAX, "%s/sys/class/net/%s/ifindex", prefix, iface); unsigned long long ifindex = 0; int ret = read_single_number_file(filename, &ifindex); @@ -63,10 +80,12 @@ unsigned int read_iface_ifindex(const char *prefix, const char *iface) { } struct iface *read_proc_net_dev(const char *prefix) { + if(!prefix) prefix = ""; + procfile *ff = NULL; char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s%s", prefix?prefix:"", "/proc/net/dev"); + snprintfz(filename, FILENAME_MAX, "%s%s", prefix, (*prefix)?"/proc/1/net/dev":"/proc/net/dev"); ff = procfile_open(filename, " \t,:|", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) { error("Cannot open file '%s'", filename); @@ -163,12 +182,14 @@ static void continue_as_child(void) { } int proc_pid_fd(const char *prefix, const char *ns, pid_t pid) { + if(!prefix) prefix = ""; + char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/proc/%d/%s", prefix?prefix:"", (int)pid, ns); + snprintfz(filename, FILENAME_MAX, "%s/proc/%d/%s", prefix, (int)pid, ns); int fd = open(filename, O_RDONLY); if(fd == -1) - error("Cannot open file '%s'", filename); + error("Cannot open proc_pid_fd() file '%s'", filename); return fd; } @@ -193,6 +214,8 @@ static struct ns { }; int switch_namespace(const char *prefix, pid_t pid) { + if(!prefix) prefix = ""; + #ifdef HAVE_SETNS int i; @@ -207,8 +230,8 @@ int switch_namespace(const char *prefix, pid_t pid) { // 2 passes - found it at nsenter source code // this is related CLONE_NEWUSER functionality - // FIXME: this code cannot switch user namespace - // Fortunately, we don't need it. + // This code cannot switch user namespace (it can all the other namespaces) + // Fortunately, we don't need to switch user namespaces. int pass, errors = 0; for(pass = 0; pass < 2 ;pass++) { @@ -272,9 +295,15 @@ int switch_namespace(const char *prefix, pid_t pid) { } pid_t read_pid_from_cgroup_file(const char *filename) { - FILE *fp = fopen(filename, "r"); + int fd = open(filename, procfile_open_flags); + if(fd == -1) { + error("Cannot open pid_from_cgroup() file '%s'.", filename); + return 0; + } + + FILE *fp = fdopen(fd, "r"); if(!fp) { - error("Cannot read file '%s'.", filename); + error("Cannot upgrade fd to fp for file '%s'.", filename); return 0; } @@ -387,14 +416,13 @@ int send_devices(void) { // since it switches namespaces, so after this call, everything is different! void detect_veth_interfaces(pid_t pid) { - struct iface *host, *cgroup, *h, *c; - const char *prefix = getenv("NETDATA_HOST_PREFIX"); + struct iface *host = NULL, *cgroup = NULL, *h, *c; - host = read_proc_net_dev(prefix); + host = read_proc_net_dev(netdata_configured_host_prefix); if(!host) { errno = 0; error("cannot read host interface list."); - return; + goto cleanup; } if(!eligible_ifaces(host)) { @@ -403,7 +431,7 @@ void detect_veth_interfaces(pid_t pid) { goto cleanup; } - if(switch_namespace(prefix, pid)) { + if(switch_namespace(netdata_configured_host_prefix, pid)) { errno = 0; error("cannot switch to the namespace of pid %u", (unsigned int) pid); goto cleanup; @@ -433,6 +461,7 @@ void detect_veth_interfaces(pid_t pid) { } cleanup: + free_host_ifaces(cgroup); free_host_ifaces(host); } @@ -444,17 +473,18 @@ void call_the_helper(pid_t pid, const char *cgroup) { if(setresuid(0, 0, 0) == -1) error("setresuid(0, 0, 0) failed."); - char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; + char command[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; if(cgroup) - snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --cgroup '%s'", cgroup); + snprintfz(command, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --cgroup '%s'", cgroup); else - snprintfz(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --pid %d", pid); + snprintfz(command, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --pid %d", pid); - info("running: %s", buffer); + info("running: %s", command); pid_t cgroup_pid; - FILE *fp = mypopene(buffer, &cgroup_pid, environment); + FILE *fp = mypopene(command, &cgroup_pid, environment); if(fp) { + char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; char *s; while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp))) { trim(s); @@ -475,7 +505,7 @@ void call_the_helper(pid_t pid, const char *cgroup) { mypclose(fp, cgroup_pid); } else - error("cannot execute cgroup-network helper script: %s", buffer); + error("cannot execute cgroup-network helper script: %s", command); } int is_valid_path_symbol(char c) { @@ -588,22 +618,23 @@ int main(int argc, char **argv) { program_version = VERSION; error_log_syslog = 0; + // since cgroup-network runs as root, prevent it from opening symbolic links + procfile_open_flags = O_RDONLY|O_NOFOLLOW; // ------------------------------------------------------------------------ // make sure NETDATA_HOST_PREFIX is safe - host_prefix = getenv("NETDATA_HOST_PREFIX"); - if(!host_prefix || !*host_prefix) - host_prefix = ""; + netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX"); + if(verify_netdata_host_prefix() == -1) exit(1); - if(host_prefix[0] != '\0' && verify_path(host_prefix) == -1) - fatal("invalid NETDATA_HOST_PREFIX '%s'", host_prefix); + if(netdata_configured_host_prefix[0] != '\0' && verify_path(netdata_configured_host_prefix) == -1) + fatal("invalid NETDATA_HOST_PREFIX '%s'", netdata_configured_host_prefix); // ------------------------------------------------------------------------ // build a safe environment for our script // the first environment variable is a fixed PATH= - snprintfz(environment_variable2, sizeof(environment_variable2) - 1, "NETDATA_HOST_PREFIX=%s", host_prefix); + snprintfz(environment_variable2, sizeof(environment_variable2) - 1, "NETDATA_HOST_PREFIX=%s", netdata_configured_host_prefix); // ------------------------------------------------------------------------ |