X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fexec.c;h=b8b538b8c765d1f09ea5312b39e384b11306c92b;hb=b5c5890955fa19651ad8b3f48d99364d270a0d8f;hp=d726f708987540102a3056422799db66d608dff9;hpb=6c9f69a4507e2ec9490e2baf76146f4036aa2b8e;p=collectd.git diff --git a/src/exec.c b/src/exec.c index d726f708..b8b538b8 100644 --- a/src/exec.c +++ b/src/exec.c @@ -22,9 +22,11 @@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_cmd_putval.h" #include #include +#include #include #include @@ -37,6 +39,7 @@ typedef struct program_list_s program_list_t; struct program_list_s { char *user; + char *group; char *exec; int pid; program_list_t *next; @@ -95,6 +98,12 @@ static int exec_config (const char *key, const char *value) pl->next = pl_head; pl_head = pl; + + pl->group = strchr (pl->user, ':'); + if (NULL != pl->group) { + *pl->group = '\0'; + pl->group++; + } } else { @@ -108,15 +117,17 @@ static void exec_child (program_list_t *pl) { int status; int uid; + int gid; + int egid; char *arg0; struct passwd *sp_ptr; struct passwd sp; - char pwnambuf[2048]; + char nambuf[2048]; char errbuf[1024]; sp_ptr = NULL; - status = getpwnam_r (pl->user, &sp, pwnambuf, sizeof (pwnambuf), &sp_ptr); + status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr); if (status != 0) { ERROR ("exec plugin: getpwnam_r failed: %s", @@ -130,17 +141,86 @@ static void exec_child (program_list_t *pl) } uid = sp.pw_uid; + gid = sp.pw_gid; if (uid == 0) { ERROR ("exec plugin: Cowardly refusing to exec program as root."); exit (-1); } + /* The group configured in the configfile is set as effective group, because + * this way the forked process can (re-)gain the user's primary group. */ + egid = -1; + if (NULL != pl->group) + { + if ('\0' != *pl->group) { + struct group *gr_ptr = NULL; + struct group gr; + + status = getgrnam_r (pl->group, &gr, nambuf, sizeof (nambuf), &gr_ptr); + if (0 != status) + { + ERROR ("exec plugin: getgrnam_r failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + exit (-1); + } + if (NULL == gr_ptr) + { + ERROR ("exec plugin: No such group: `%s'", pl->group); + exit (-1); + } + + egid = gr.gr_gid; + } + else + { + egid = gid; + } + } /* if (pl->group == NULL) */ + +#if HAVE_SETGROUPS + if (getuid () == 0) + { + gid_t glist[2]; + size_t glist_len; + + glist[0] = gid; + glist_len = 1; + + if (gid != egid) + { + glist[1] = egid; + glist_len = 2; + } + + setgroups (glist_len, glist); + } +#endif /* HAVE_SETGROUPS */ + + status = setgid (gid); + if (status != 0) + { + ERROR ("exec plugin: setgid (%i) failed: %s", + gid, sstrerror (errno, errbuf, sizeof (errbuf))); + exit (-1); + } + + if (egid != -1) + { + status = setegid (egid); + if (status != 0) + { + ERROR ("exec plugin: setegid (%i) failed: %s", + egid, sstrerror (errno, errbuf, sizeof (errbuf))); + exit (-1); + } + } + status = setuid (uid); if (status != 0) { - ERROR ("exec plugin: setuid failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); + ERROR ("exec plugin: setuid (%i) failed: %s", + uid, sstrerror (errno, errbuf, sizeof (errbuf))); exit (-1); } @@ -204,79 +284,13 @@ static int fork_child (program_list_t *pl) static int parse_line (char *buffer) { - char *fields[4]; + char *fields[256]; int fields_num; - char *hostname; - char *plugin; - char *plugin_instance; - char *type; - char *type_instance; - - const data_set_t *ds; - value_list_t vl = VALUE_LIST_INIT; - - int status; - - fields_num = strsplit (buffer, fields, 4); - if (fields_num != 2) - { - WARNING ("exec plugin: Number of fields is not 2."); - return (-1); - } - - status = parse_identifier (fields[0], &hostname, - &plugin, &plugin_instance, - &type, &type_instance); - if (status != 0) - { - WARNING ("exec plugin: Cannot parse `%s'", fields[0]); - return (-1); - } - - if ((strlen (hostname) >= sizeof (vl.host)) - || (strlen (plugin) >= sizeof (vl.plugin)) - || ((plugin_instance != NULL) - && (strlen (plugin_instance) >= sizeof (vl.plugin_instance))) - || ((type_instance != NULL) - && (strlen (type_instance) >= sizeof (vl.type_instance)))) - { - WARNING ("exec plugin: An identifier is too long."); - return (-1); - } - - strcpy (vl.host, hostname); - strcpy (vl.plugin, plugin); - if (plugin_instance != NULL) - strcpy (vl.plugin_instance, plugin_instance); - if (type_instance != NULL) - strcpy (vl.type_instance, type_instance); - - ds = plugin_get_ds (type); - if (ds == NULL) - { - WARNING ("exec plugin: No such type: `%s'", type); - return (-1); - } - - vl.values_len = ds->ds_num; - vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len); - if (vl.values == NULL) - return (-1); - - /* Sets vl.values and vl.time */ - status = parse_values (fields[1], &vl, ds); - if (status != 0) - { - WARNING ("exec plugin: Cannot parse `%s'", fields[1]); - sfree (vl.values); - return (-1); - } - - plugin_dispatch_values (type, &vl); + fields[0] = "PUTVAL"; + fields_num = strsplit (buffer, &fields[1], STATIC_ARRAY_SIZE(fields) - 1); - sfree (vl.values); - + handle_putval (stdout, fields, fields_num + 1); return (0); } /* int parse_line */ @@ -300,6 +314,7 @@ static void *exec_read_one (void *arg) ERROR ("exec plugin: fdopen (%i) failed: %s", fd, sstrerror (errno, errbuf, sizeof (errbuf))); kill (pl->pid, SIGTERM); + pl->pid = 0; close (fd); pthread_exit ((void *) 1); }