From: Florian Forster Date: Thu, 11 Aug 2016 15:10:13 +0000 (+0200) Subject: Merge remote-tracking branch 'github/pr/1530' X-Git-Tag: collectd-5.6.0~57 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=08cf386cb8aa711ef4043d9139d464b38188a44b;hp=8737bfd2e356a35bbef30ed2185c566cd61bca0b;p=collectd.git Merge remote-tracking branch 'github/pr/1530' --- diff --git a/src/ceph.c b/src/ceph.c index cbfdd22c..5248a1ac 100644 --- a/src/ceph.c +++ b/src/ceph.c @@ -38,6 +38,9 @@ #if HAVE_YAJL_YAJL_VERSION_H #include #endif +#ifdef HAVE_SYS_CAPABILITY_H +# include +#endif #include #include @@ -1573,6 +1576,22 @@ static int ceph_read(void) static int ceph_init(void) { int ret; + +#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_DAC_OVERRIDE) + if (check_capability (CAP_DAC_OVERRIDE) != 0) + { + if (getuid () == 0) + WARNING ("ceph plugin: Running collectd as root, but the " + "CAP_DAC_OVERRIDE capability is missing. The plugin's read " + "function will probably fail. Is your init system dropping " + "capabilities?"); + else + WARNING ("ceph plugin: collectd doesn't have the CAP_DAC_OVERRIDE " + "capability. If you don't want to run collectd as root, try running " + "\"setcap cap_dac_override=ep\" on the collectd binary."); + } +#endif + ceph_daemons_print(); ret = cconn_main_loop(ASOK_REQ_VERSION); diff --git a/src/daemon/common.c b/src/daemon/common.c index c6559a80..45f9d533 100644 --- a/src/daemon/common.c +++ b/src/daemon/common.c @@ -60,6 +60,10 @@ # include #endif +#ifdef HAVE_SYS_CAPABILITY_H +# include +#endif + #ifdef HAVE_LIBKSTAT extern kstat_ctl_t *kc; #endif @@ -1668,3 +1672,52 @@ void strarray_free (char **array, size_t array_len) /* {{{ */ sfree (array[i]); sfree (array); } /* }}} void strarray_free */ + +#ifdef HAVE_SYS_CAPABILITY_H +int check_capability (int capability) /* {{{ */ +{ +#ifdef _LINUX_CAPABILITY_VERSION_3 + cap_user_header_t cap_header = calloc(sizeof (*cap_header), 1); + if (cap_header == NULL) + { + ERROR("check_capability: calloc failed"); + return (-1); + } + + cap_user_data_t cap_data = calloc(sizeof (*cap_data), 1); + if (cap_data == NULL) + { + ERROR("check_capability: calloc failed"); + sfree(cap_header); + return (-1); + } + + cap_header->pid = getpid(); + cap_header->version = _LINUX_CAPABILITY_VERSION; + if (capget(cap_header, cap_data) < 0) + { + ERROR("check_capability: capget failed"); + sfree(cap_header); + sfree(cap_data); + return (-1); + } + + if ((cap_data->effective & (1 << capability)) == 0) + { + sfree(cap_header); + sfree(cap_data); + return (-1); + } + else + { + sfree(cap_header); + sfree(cap_data); + return (0); + } +#else + WARNING ("check_capability: unsupported capability implementation. " + "Some plugin(s) may require elevated privileges to work properly."); + return (0); +#endif /* _LINUX_CAPABILITY_VERSION_3 */ +} /* }}} int check_capability */ +#endif /* HAVE_SYS_CAPABILITY_H */ diff --git a/src/daemon/common.h b/src/daemon/common.h index 5ad2b50d..720e5f1b 100644 --- a/src/daemon/common.h +++ b/src/daemon/common.h @@ -375,4 +375,12 @@ int strtogauge (const char *string, gauge_t *ret_value); int strarray_add (char ***ret_array, size_t *ret_array_len, char const *str); void strarray_free (char **array, size_t array_len); +#ifdef HAVE_SYS_CAPABILITY_H +/** Check if the current process benefits from the capability passed in + * argument. Returns zero if it does, less than zero if it doesn't or on error. + * See capabilities(7) for the list of possible capabilities. + * */ +int check_capability (int capability); +#endif /* HAVE_SYS_CAPABILITY_H */ + #endif /* COMMON_H */ diff --git a/src/dns.c b/src/dns.c index 15fa15a7..a2a4667a 100644 --- a/src/dns.c +++ b/src/dns.c @@ -35,6 +35,10 @@ #include +#ifdef HAVE_SYS_CAPABILITY_H +# include +#endif + /* * Private data types */ @@ -347,6 +351,20 @@ static int dns_init (void) listen_thread_init = 1; +#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_RAW) + if (check_capability (CAP_NET_RAW) != 0) + { + if (getuid () == 0) + WARNING ("dns plugin: Running collectd as root, but the CAP_NET_RAW " + "capability is missing. The plugin's read function will probably " + "fail. Is your init system dropping capabilities?"); + else + WARNING ("dns plugin: collectd doesn't have the CAP_NET_RAW capability. " + "If you don't want to run collectd as root, try running \"setcap " + "cap_net_raw=ep\" on the collectd binary."); + } +#endif + return (0); } /* int dns_init */ diff --git a/src/exec.c b/src/exec.c index e90f83c9..dfd4b05f 100644 --- a/src/exec.c +++ b/src/exec.c @@ -39,6 +39,10 @@ #include #include +#ifdef HAVE_SYS_CAPABILITY_H +# include +#endif + #define PL_NORMAL 0x01 #define PL_NOTIF_ACTION 0x02 @@ -806,6 +810,22 @@ static int exec_init (void) /* {{{ */ sigaction (SIGCHLD, &sa, NULL); +#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SETUID) && defined(CAP_SETGID) + if ((check_capability (CAP_SETUID) != 0) || + (check_capability (CAP_SETGID) != 0)) + { + if (getuid () == 0) + WARNING ("exec plugin: Running collectd as root, but the CAP_SETUID " + "or CAP_SETGID capabilities are missing. The plugin's read function " + "will probably fail. Is your init system dropping capabilities?"); + else + WARNING ("exec plugin: collectd doesn't have the CAP_SETUID or " + "CAP_SETGID capabilities. If you don't want to run collectd as root, " + "try running \"setcap 'cap_setuid=ep cap_setgid=ep'\" on the " + "collectd binary."); + } +#endif + return (0); } /* int exec_init }}} */ diff --git a/src/iptables.c b/src/iptables.c index e035a888..35c93f4e 100644 --- a/src/iptables.c +++ b/src/iptables.c @@ -33,6 +33,10 @@ #include #include +#ifdef HAVE_SYS_CAPABILITY_H +# include +#endif + /* * iptc_handle_t was available before libiptc was officially available as a * shared library. Note, that when the shared lib was introduced, the API and @@ -499,10 +503,30 @@ static int iptables_shutdown (void) return (0); } /* int iptables_shutdown */ +static int iptables_init (void) +{ +#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_ADMIN) + if (check_capability (CAP_NET_ADMIN) != 0) + { + if (getuid () == 0) + WARNING ("iptables plugin: Running collectd as root, but the " + "CAP_NET_ADMIN capability is missing. The plugin's read " + "function will probably fail. Is your init system dropping " + "capabilities?"); + else + WARNING ("iptables plugin: collectd doesn't have the CAP_NET_ADMIN " + "capability. If you don't want to run collectd as root, try " + "running \"setcap cap_net_admin=ep\" on the collectd binary."); + } +#endif + return (0); +} /* int iptables_init */ + void module_register (void) { plugin_register_config ("iptables", iptables_config, config_keys, config_keys_num); + plugin_register_init ("iptables", iptables_init); plugin_register_read ("iptables", iptables_read); plugin_register_shutdown ("iptables", iptables_shutdown); } /* void module_register */ diff --git a/src/ping.c b/src/ping.c index 4932bae5..52db2c71 100644 --- a/src/ping.c +++ b/src/ping.c @@ -36,6 +36,10 @@ # include /* NI_MAXHOST */ #endif +#ifdef HAVE_SYS_CAPABILITY_H +# include +#endif + #include #ifndef NI_MAXHOST @@ -448,6 +452,20 @@ static int ping_init (void) /* {{{ */ "Will use a timeout of %gs.", ping_timeout); } +#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_RAW) + if (check_capability (CAP_NET_RAW) != 0) + { + if (getuid () == 0) + WARNING ("ping plugin: Running collectd as root, but the CAP_NET_RAW " + "capability is missing. The plugin's read function will probably " + "fail. Is your init system dropping capabilities?"); + else + WARNING ("ping plugin: collectd doesn't have the CAP_NET_RAW capability. " + "If you don't want to run collectd as root, try running \"setcap " + "cap_net_raw=ep\" on the collectd binary."); + } +#endif + return (start_thread ()); } /* }}} int ping_init */ diff --git a/src/turbostat.c b/src/turbostat.c index 913511f7..2d8a08e6 100644 --- a/src/turbostat.c +++ b/src/turbostat.c @@ -1474,35 +1474,22 @@ out: static int check_permissions(void) { -#ifdef HAVE_SYS_CAPABILITY_H - struct __user_cap_header_struct cap_header_data; - cap_user_header_t cap_header = &cap_header_data; - struct __user_cap_data_struct cap_data_data; - cap_user_data_t cap_data = &cap_data_data; - int ret = 0; -#endif /* HAVE_SYS_CAPABILITY_H */ if (getuid() == 0) { /* We have everything we need */ return 0; -#ifndef HAVE_SYS_CAPABILITY_H +#if !defined(HAVE_SYS_CAPABILITY_H) && !defined(CAP_SYS_RAWIO) } else { ERROR("turbostat plugin: Initialization failed: this plugin " "requires collectd to run as root"); return -1; } -#else /* HAVE_SYS_CAPABILITY_H */ +#else /* HAVE_SYS_CAPABILITY_H && CAP_SYS_RAWIO */ } - /* check for CAP_SYS_RAWIO */ - cap_header->pid = getpid(); - cap_header->version = _LINUX_CAPABILITY_VERSION; - if (capget(cap_header, cap_data) < 0) { - ERROR("turbostat plugin: capget failed"); - return -1; - } + int ret = 0; - if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) { + if (check_capability(CAP_SYS_RAWIO) != 0) { WARNING("turbostat plugin: Collectd doesn't have the " "CAP_SYS_RAWIO capability. If you don't want to run " "collectd as root, try running \"setcap " @@ -1524,7 +1511,7 @@ check_permissions(void) "collectd a special capability (CAP_SYS_RAWIO) and read " "access to /dev/cpu/*/msr (see previous warnings)"); return ret; -#endif /* HAVE_SYS_CAPABILITY_H */ +#endif /* HAVE_SYS_CAPABILITY_H && CAP_SYS_RAWIO */ } static int