X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fexec.c;h=e0d1f890441c7eff7c099c55d435907aa4f708bc;hb=92b269e2d433759066c621f7cf4d34bbc1ce78e8;hp=28380ac33677788acd1ffc2b4058ba08a9661e53;hpb=01d23e3f5daf016d03f82d92a76be2fe3decdca4;p=collectd.git diff --git a/src/exec.c b/src/exec.c index 28380ac3..e0d1f890 100644 --- a/src/exec.c +++ b/src/exec.c @@ -78,6 +78,11 @@ typedef struct program_list_and_notification_s { } program_list_and_notification_t; /* + * constants + */ +const long int MAX_GRBUF_SIZE = 65536; + +/* * Private variables */ static program_list_t *pl_head = NULL; @@ -348,6 +353,67 @@ static void close_pipe(int fd_pipe[2]) /* {{{ */ } /* }}} void close_pipe */ /* + * Get effective group ID from group name. + * Input arguments: + * pl :program list struct with group name + * gid :group id to fallback in case egid cannot be determined. + * Returns: + * egid effective group id if successfull, + * -1 if group is not defined/not found. + * -2 for any buffer allocation error. + */ +static int getegr_id(program_list_t *pl, int gid) /* {{{ */ +{ + if (pl->group == NULL) { + return -1; + } + if (strcmp(pl->group, "") == 0) { + return gid; + } + struct group *gr_ptr = NULL; + struct group gr; + + long int grbuf_size = sysconf(_SC_GETGR_R_SIZE_MAX); + if (grbuf_size <= 0) + grbuf_size = sysconf(_SC_PAGESIZE); + if (grbuf_size <= 0) + grbuf_size = 4096; + + char *temp = NULL; + char *grbuf = NULL; + + do { + temp = realloc(grbuf, grbuf_size); + if (temp == NULL) { + ERROR("exec plugin: getegr_id for %s: realloc buffer[%ld] failed ", + pl->group, grbuf_size); + sfree(grbuf); + return -2; + } + grbuf = temp; + if (getgrnam_r(pl->group, &gr, grbuf, grbuf_size, &gr_ptr) == 0) { + sfree(grbuf); + if (gr_ptr == NULL) { + ERROR("exec plugin: No such group: `%s'", pl->group); + return -1; + } + return gr.gr_gid; + } else if (errno == ERANGE) { + grbuf_size += grbuf_size; // increment buffer size and try again + } else { + char errbuf[1024]; + ERROR("exec plugin: getegr_id failed %s", + sstrerror(errno, errbuf, sizeof(errbuf))); + sfree(grbuf); + return -2; + } + } while (grbuf_size <= MAX_GRBUF_SIZE); + ERROR("exec plugin: getegr_id Max grbuf size reached for %s", pl->group); + sfree(grbuf); + return -2; +} /* }}} */ + +/* * Creates three pipes (one for reading, one for writing and one for errors), * forks a child, sets up the pipes so that fd_in is connected to STDIN of * the child and fd_out is connected to STDOUT and fd_err is connected to STDERR @@ -369,11 +435,17 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, struct passwd *sp_ptr; struct passwd sp; - char nambuf[4096]; if (pl->pid != 0) return (-1); + long int nambuf_size = sysconf(_SC_GETPW_R_SIZE_MAX); + if (nambuf_size <= 0) + nambuf_size = sysconf(_SC_PAGESIZE); + if (nambuf_size <= 0) + nambuf_size = 4096; + char nambuf[nambuf_size]; + if ((create_pipe(fd_pipe_in) == -1) || (create_pipe(fd_pipe_out) == -1) || (create_pipe(fd_pipe_err) == -1)) goto failed; @@ -398,31 +470,10 @@ static int fork_child(program_list_t *pl, int *fd_in, int *fd_out, goto failed; } - /* 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: Failed to get group information " - "for group ``%s'': %s", - pl->group, sstrerror(status, errbuf, sizeof(errbuf))); - goto failed; - } - if (NULL == gr_ptr) { - ERROR("exec plugin: No such group: `%s'", pl->group); - goto failed; - } - - egid = gr.gr_gid; - } else { - egid = gid; - } - } /* if (pl->group == NULL) */ + egid = getegr_id(pl, gid); + if (egid == -2) { + goto failed; + } pid = fork(); if (pid < 0) { @@ -787,7 +838,11 @@ static int exec_read(void) /* {{{ */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - plugin_thread_create(&t, &attr, exec_read_one, (void *)pl, "exec read"); + int status = + plugin_thread_create(&t, &attr, exec_read_one, (void *)pl, "exec read"); + if (status != 0) { + ERROR("exec plugin: plugin_thread_create failed."); + } pthread_attr_destroy(&attr); } /* for (pl) */ @@ -826,8 +881,11 @@ static int exec_notification(const notification_t *n, /* {{{ */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - plugin_thread_create(&t, &attr, exec_notification_one, (void *)pln, - "exec notify"); + int status = plugin_thread_create(&t, &attr, exec_notification_one, + (void *)pln, "exec notify"); + if (status != 0) { + ERROR("exec plugin: plugin_thread_create failed."); + } pthread_attr_destroy(&attr); } /* for (pl) */