X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fexec.c;h=85f6cb8038a21b12a0db63668164b3585d885577;hb=56cfc69d0a124c80036b73c2ef1c192706097faa;hp=fbd9c268bcd74102ef0381ea11023944a9d59baf;hpb=344be4992285313e8855c8114993b692ae08775e;p=collectd.git diff --git a/src/exec.c b/src/exec.c index fbd9c268..85f6cb80 100644 --- a/src/exec.c +++ b/src/exec.c @@ -18,11 +18,12 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: - * Florian octo Forster + * Florian octo Forster * Sebastian Harl * Peter Holik **/ +#define _DEFAULT_SOURCE #define _BSD_SOURCE /* For setgroups */ #include "collectd.h" @@ -125,13 +126,12 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */ return (-1); } - pl = (program_list_t *) malloc (sizeof (program_list_t)); + pl = calloc (1, sizeof (*pl)); if (pl == NULL) { - ERROR ("exec plugin: malloc failed."); + ERROR ("exec plugin: calloc failed."); return (-1); } - memset (pl, '\0', sizeof (program_list_t)); if (strcasecmp ("NotificationExec", ci->key) == 0) pl->flags |= PL_NOTIF_ACTION; @@ -162,16 +162,15 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */ return (-1); } - pl->argv = (char **) malloc (ci->values_num * sizeof (char *)); + pl->argv = calloc (ci->values_num, sizeof (*pl->argv)); if (pl->argv == NULL) { - ERROR ("exec plugin: malloc failed."); + ERROR ("exec plugin: calloc failed."); sfree (pl->exec); sfree (pl->user); sfree (pl); return (-1); } - memset (pl->argv, '\0', ci->values_num * sizeof (char *)); { char *tmp = strrchr (ci->values[1].value.string, '/'); @@ -183,7 +182,7 @@ static int exec_config_exec (oconfig_item_t *ci) /* {{{ */ pl->argv[0] = strdup (buffer); if (pl->argv[0] == NULL) { - ERROR ("exec plugin: malloc failed."); + ERROR ("exec plugin: strdup failed."); sfree (pl->argv); sfree (pl->exec); sfree (pl->user); @@ -287,71 +286,11 @@ static void set_environment (void) /* {{{ */ } /* }}} void set_environment */ __attribute__((noreturn)) -static void exec_child (program_list_t *pl) /* {{{ */ +static void exec_child (program_list_t *pl, int uid, int gid, int egid) /* {{{ */ { int status; - int uid; - int gid; - int egid; - - struct passwd *sp_ptr; - struct passwd sp; - char nambuf[2048]; char errbuf[1024]; - sp_ptr = NULL; - status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr); - if (status != 0) - { - ERROR ("exec plugin: Failed to get user information for user ``%s'': %s", - pl->user, sstrerror (errno, errbuf, sizeof (errbuf))); - exit (-1); - } - if (sp_ptr == NULL) - { - ERROR ("exec plugin: No such user: `%s'", pl->user); - exit (-1); - } - - 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: Failed to get group information " - "for group ``%s'': %s", pl->group, - 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) { @@ -398,7 +337,7 @@ static void exec_child (program_list_t *pl) /* {{{ */ exit (-1); } - status = execvp (pl->exec, pl->argv); + execvp (pl->exec, pl->argv); ERROR ("exec plugin: Failed to execute ``%s'': %s", pl->exec, sstrerror (errno, errbuf, sizeof (errbuf))); @@ -414,6 +353,31 @@ static void reset_signal_mask (void) /* {{{ */ sigprocmask (SIG_SETMASK, &ss, /* old mask = */ NULL); } /* }}} void reset_signal_mask */ +static int create_pipe (int fd_pipe[2]) /* {{{ */ +{ + char errbuf[1024]; + int status; + + status = pipe (fd_pipe); + if (status != 0) + { + ERROR ("exec plugin: pipe failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } + + return 0; +} /* }}} int create_pipe */ + +static void close_pipe (int fd_pipe[2]) /* {{{ */ +{ + if (fd_pipe[0] != -1) + close (fd_pipe[0]); + + if (fd_pipe[1] != -1) + close (fd_pipe[1]); +} /* }}} void close_pipe */ + /* * 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 @@ -422,46 +386,89 @@ static void reset_signal_mask (void) /* {{{ */ */ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err) /* {{{ */ { - int fd_pipe_in[2]; - int fd_pipe_out[2]; - int fd_pipe_err[2]; + int fd_pipe_in[2] = {-1, -1}; + int fd_pipe_out[2] = {-1, -1}; + int fd_pipe_err[2] = {-1, -1}; char errbuf[1024]; int status; int pid; + int uid; + int gid; + int egid; + + struct passwd *sp_ptr; + struct passwd sp; + char nambuf[2048]; + if (pl->pid != 0) return (-1); - status = pipe (fd_pipe_in); + if ((create_pipe(fd_pipe_in) == -1) + || (create_pipe(fd_pipe_out) == -1) + || (create_pipe(fd_pipe_err) == -1)) + goto failed; + + sp_ptr = NULL; + status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr); if (status != 0) { - ERROR ("exec plugin: pipe failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return (-1); + ERROR ("exec plugin: Failed to get user information for user ``%s'': %s", + pl->user, sstrerror (errno, errbuf, sizeof (errbuf))); + goto failed; } - status = pipe (fd_pipe_out); - if (status != 0) + if (sp_ptr == NULL) { - ERROR ("exec plugin: pipe failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return (-1); + ERROR ("exec plugin: No such user: `%s'", pl->user); + goto failed; } - status = pipe (fd_pipe_err); - if (status != 0) + uid = sp.pw_uid; + gid = sp.pw_gid; + if (uid == 0) { - ERROR ("exec plugin: pipe failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - return (-1); + ERROR ("exec plugin: Cowardly refusing to exec program as root."); + 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 (errno, 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) */ + pid = fork (); if (pid < 0) { ERROR ("exec plugin: fork failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); - return (-1); + goto failed; } else if (pid == 0) { @@ -505,7 +512,7 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err) /* Unblock all signals */ reset_signal_mask (); - exec_child (pl); + exec_child (pl, uid, gid, egid); /* does not return */ } @@ -529,6 +536,13 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err) close (fd_pipe_err[0]); return (pid); + +failed: + close_pipe(fd_pipe_in); + close_pipe(fd_pipe_out); + close_pipe(fd_pipe_err); + + return (-1); } /* int fork_child }}} */ static int parse_line (char *buffer) /* {{{ */ @@ -853,8 +867,7 @@ static int exec_notification (const notification_t *n, /* {{{ */ if (pl->pid != 0) continue; - pln = (program_list_and_notification_t *) malloc (sizeof - (program_list_and_notification_t)); + pln = malloc (sizeof (*pln)); if (pln == NULL) { ERROR ("exec plugin: malloc failed.");