1 /*
2  * Copyright 2010-2019 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 
10 #ifndef _GNU_SOURCE
11 #  define _GNU_SOURCE
12 #endif
13 
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/wait.h>
17 #include <errno.h>
18 #include <unistd.h>
19 #include <dirent.h>
20 #include <string.h>
21 #include <sys/time.h>
22 #include <sys/resource.h>
23 
24 #include "crm/crm.h"
25 #include "crm/common/mainloop.h"
26 #include "crm/services.h"
27 
28 #include "services_private.h"
29 
30 #if SUPPORT_CIBSECRETS
31 #  include "crm/common/cib_secrets.h"
32 #endif
33 
34 /* We have two alternative ways of handling SIGCHLD when synchronously waiting
35  * for spawned processes to complete. Both rely on polling a file descriptor to
36  * discover SIGCHLD events.
37  *
38  * If sys/signalfd.h is available (e.g. on Linux), we call signalfd() to
39  * generate the file descriptor. Otherwise, we use the "self-pipe trick"
40  * (opening a pipe and writing a byte to it when SIGCHLD is received).
41  */
42 #ifdef HAVE_SYS_SIGNALFD_H
43 
44 // signalfd() implementation
45 
46 #include <sys/signalfd.h>
47 
48 // Everything needed to manage SIGCHLD handling
49 struct sigchld_data_s {
50     sigset_t mask;      // Signals to block now (including SIGCHLD)
51     sigset_t old_mask;  // Previous set of blocked signals
52 };
53 
54 // Initialize SIGCHLD data and prepare for use
55 static void
sigchld_setup(struct sigchld_data_s * data)56 sigchld_setup(struct sigchld_data_s *data)
57 {
58     sigemptyset(&(data->mask));
59     sigaddset(&(data->mask), SIGCHLD);
60 
61     sigemptyset(&(data->old_mask));
62 
63     // Block SIGCHLD (saving previous set of blocked signals to restore later)
64     if (sigprocmask(SIG_BLOCK, &(data->mask), &(data->old_mask)) < 0) {
65         crm_perror(LOG_ERR, "sigprocmask() failed to block sigchld");
66     }
67 }
68 
69 // Get a file descriptor suitable for polling for SIGCHLD events
70 static int
sigchld_open(struct sigchld_data_s * data)71 sigchld_open(struct sigchld_data_s *data)
72 {
73     int fd;
74 
75     CRM_CHECK(data != NULL, return -1);
76 
77     fd = signalfd(-1, &(data->mask), SFD_NONBLOCK);
78     if (fd < 0) {
79         crm_perror(LOG_ERR, "signalfd() failed");
80     }
81     return fd;
82 }
83 
84 // Close a file descriptor returned by sigchld_open()
85 static void
sigchld_close(int fd)86 sigchld_close(int fd)
87 {
88     if (fd > 0) {
89         close(fd);
90     }
91 }
92 
93 // Return true if SIGCHLD was received from polled fd
94 static bool
sigchld_received(int fd)95 sigchld_received(int fd)
96 {
97     struct signalfd_siginfo fdsi;
98     ssize_t s;
99 
100     s = read(fd, &fdsi, sizeof(struct signalfd_siginfo));
101     if (s != sizeof(struct signalfd_siginfo)) {
102         crm_perror(LOG_ERR, "Read from signal fd %d failed", fd);
103 
104     } else if (fdsi.ssi_signo == SIGCHLD) {
105         return true;
106     }
107     return false;
108 }
109 
110 // Do anything needed after done waiting for SIGCHLD
111 static void
sigchld_cleanup(struct sigchld_data_s * data)112 sigchld_cleanup(struct sigchld_data_s *data)
113 {
114     // Restore the original set of blocked signals
115     if ((sigismember(&(data->old_mask), SIGCHLD) == 0)
116         && (sigprocmask(SIG_UNBLOCK, &(data->mask), NULL) < 0)) {
117         crm_perror(LOG_ERR, "sigprocmask() failed to unblock sigchld");
118     }
119 }
120 
121 #else // HAVE_SYS_SIGNALFD_H not defined
122 
123 // Self-pipe implementation (see above for function descriptions)
124 
125 struct sigchld_data_s {
126     int pipe_fd[2];             // Pipe file descriptors
127     struct sigaction sa;        // Signal handling info (with SIGCHLD)
128     struct sigaction old_sa;    // Previous signal handling info
129 };
130 
131 // We need a global to use in the signal handler
132 volatile struct sigchld_data_s *last_sigchld_data = NULL;
133 
134 static void
sigchld_handler()135 sigchld_handler()
136 {
137     // We received a SIGCHLD, so trigger pipe polling
138     if ((last_sigchld_data != NULL)
139         && (last_sigchld_data->pipe_fd[1] >= 0)
140         && (write(last_sigchld_data->pipe_fd[1], "", 1) == -1)) {
141         crm_perror(LOG_TRACE, "Could not poke SIGCHLD self-pipe");
142     }
143 }
144 
145 static void
sigchld_setup(struct sigchld_data_s * data)146 sigchld_setup(struct sigchld_data_s *data)
147 {
148     int rc;
149 
150     data->pipe_fd[0] = data->pipe_fd[1] = -1;
151 
152     if (pipe(data->pipe_fd) == -1) {
153         crm_perror(LOG_ERR, "pipe() failed");
154     }
155 
156     rc = crm_set_nonblocking(data->pipe_fd[0]);
157     if (rc < 0) {
158         crm_warn("Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
159                  pcmk_strerror(rc), rc);
160     }
161     rc = crm_set_nonblocking(data->pipe_fd[1]);
162     if (rc < 0) {
163         crm_warn("Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
164                  pcmk_strerror(rc), rc);
165     }
166 
167     // Set SIGCHLD handler
168     data->sa.sa_handler = sigchld_handler;
169     data->sa.sa_flags = 0;
170     sigemptyset(&(data->sa.sa_mask));
171     if (sigaction(SIGCHLD, &(data->sa), &(data->old_sa)) < 0) {
172         crm_perror(LOG_ERR, "sigaction() failed to set sigchld handler");
173     }
174 
175     // Remember data for use in signal handler
176     last_sigchld_data = data;
177 }
178 
179 static int
sigchld_open(struct sigchld_data_s * data)180 sigchld_open(struct sigchld_data_s *data)
181 {
182     CRM_CHECK(data != NULL, return -1);
183     return data->pipe_fd[0];
184 }
185 
186 static void
sigchld_close(int fd)187 sigchld_close(int fd)
188 {
189     // Pipe will be closed in sigchld_cleanup()
190     return;
191 }
192 
193 static bool
sigchld_received(int fd)194 sigchld_received(int fd)
195 {
196     char ch;
197 
198     // Clear out the self-pipe
199     while (read(fd, &ch, 1) == 1) /*omit*/;
200     return true;
201 }
202 
203 static void
sigchld_cleanup(struct sigchld_data_s * data)204 sigchld_cleanup(struct sigchld_data_s *data)
205 {
206     // Restore the previous SIGCHLD handler
207     if (sigaction(SIGCHLD, &(data->old_sa), NULL) < 0) {
208         crm_perror(LOG_ERR, "sigaction() failed to remove sigchld handler");
209     }
210 
211     // Close the pipe
212     if (data->pipe_fd[0] >= 0) {
213         close(data->pipe_fd[0]);
214         data->pipe_fd[0] = -1;
215     }
216     if (data->pipe_fd[1] >= 0) {
217         close(data->pipe_fd[1]);
218         data->pipe_fd[1] = -1;
219     }
220 }
221 
222 #endif
223 
224 static gboolean
svc_read_output(int fd,svc_action_t * op,bool is_stderr)225 svc_read_output(int fd, svc_action_t * op, bool is_stderr)
226 {
227     char *data = NULL;
228     int rc = 0, len = 0;
229     char buf[500];
230     static const size_t buf_read_len = sizeof(buf) - 1;
231 
232 
233     if (fd < 0) {
234         crm_trace("No fd for %s", op->id);
235         return FALSE;
236     }
237 
238     if (is_stderr && op->stderr_data) {
239         len = strlen(op->stderr_data);
240         data = op->stderr_data;
241         crm_trace("Reading %s stderr into offset %d", op->id, len);
242 
243     } else if (is_stderr == FALSE && op->stdout_data) {
244         len = strlen(op->stdout_data);
245         data = op->stdout_data;
246         crm_trace("Reading %s stdout into offset %d", op->id, len);
247 
248     } else {
249         crm_trace("Reading %s %s into offset %d", op->id, is_stderr?"stderr":"stdout", len);
250     }
251 
252     do {
253         rc = read(fd, buf, buf_read_len);
254         if (rc > 0) {
255             buf[rc] = 0;
256             crm_trace("Got %d chars: %.80s", rc, buf);
257             data = realloc_safe(data, len + rc + 1);
258             len += sprintf(data + len, "%s", buf);
259 
260         } else if (errno != EINTR) {
261             /* error or EOF
262              * Cleanup happens in pipe_done()
263              */
264             rc = FALSE;
265             break;
266         }
267 
268     } while (rc == buf_read_len || rc < 0);
269 
270     if (is_stderr) {
271         op->stderr_data = data;
272     } else {
273         op->stdout_data = data;
274     }
275 
276     return rc;
277 }
278 
279 static int
dispatch_stdout(gpointer userdata)280 dispatch_stdout(gpointer userdata)
281 {
282     svc_action_t *op = (svc_action_t *) userdata;
283 
284     return svc_read_output(op->opaque->stdout_fd, op, FALSE);
285 }
286 
287 static int
dispatch_stderr(gpointer userdata)288 dispatch_stderr(gpointer userdata)
289 {
290     svc_action_t *op = (svc_action_t *) userdata;
291 
292     return svc_read_output(op->opaque->stderr_fd, op, TRUE);
293 }
294 
295 static void
pipe_out_done(gpointer user_data)296 pipe_out_done(gpointer user_data)
297 {
298     svc_action_t *op = (svc_action_t *) user_data;
299 
300     crm_trace("%p", op);
301 
302     op->opaque->stdout_gsource = NULL;
303     if (op->opaque->stdout_fd > STDOUT_FILENO) {
304         close(op->opaque->stdout_fd);
305     }
306     op->opaque->stdout_fd = -1;
307 }
308 
309 static void
pipe_err_done(gpointer user_data)310 pipe_err_done(gpointer user_data)
311 {
312     svc_action_t *op = (svc_action_t *) user_data;
313 
314     op->opaque->stderr_gsource = NULL;
315     if (op->opaque->stderr_fd > STDERR_FILENO) {
316         close(op->opaque->stderr_fd);
317     }
318     op->opaque->stderr_fd = -1;
319 }
320 
321 static struct mainloop_fd_callbacks stdout_callbacks = {
322     .dispatch = dispatch_stdout,
323     .destroy = pipe_out_done,
324 };
325 
326 static struct mainloop_fd_callbacks stderr_callbacks = {
327     .dispatch = dispatch_stderr,
328     .destroy = pipe_err_done,
329 };
330 
331 static void
set_ocf_env(const char * key,const char * value,gpointer user_data)332 set_ocf_env(const char *key, const char *value, gpointer user_data)
333 {
334     if (setenv(key, value, 1) != 0) {
335         crm_perror(LOG_ERR, "setenv failed for key:%s and value:%s", key, value);
336     }
337 }
338 
339 static void
set_ocf_env_with_prefix(gpointer key,gpointer value,gpointer user_data)340 set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data)
341 {
342     char buffer[500];
343 
344     snprintf(buffer, sizeof(buffer), "OCF_RESKEY_%s", (char *)key);
345     set_ocf_env(buffer, value, user_data);
346 }
347 
348 static void
set_alert_env(gpointer key,gpointer value,gpointer user_data)349 set_alert_env(gpointer key, gpointer value, gpointer user_data)
350 {
351     int rc;
352 
353     if (value != NULL) {
354         rc = setenv(key, value, 1);
355     } else {
356         rc = unsetenv(key);
357     }
358 
359     if (rc < 0) {
360         crm_perror(LOG_ERR, "setenv %s=%s",
361                   (char*)key, (value? (char*)value : ""));
362     } else {
363         crm_trace("setenv %s=%s", (char*)key, (value? (char*)value : ""));
364     }
365 }
366 
367 /*!
368  * \internal
369  * \brief Add environment variables suitable for an action
370  *
371  * \param[in] op  Action to use
372  */
373 static void
add_action_env_vars(const svc_action_t * op)374 add_action_env_vars(const svc_action_t *op)
375 {
376     void (*env_setter)(gpointer, gpointer, gpointer) = NULL;
377     if (op->agent == NULL) {
378         env_setter = set_alert_env;  /* we deal with alert handler */
379 
380     } else if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_OCF)) {
381         env_setter = set_ocf_env_with_prefix;
382     }
383 
384     if (env_setter != NULL && op->params != NULL) {
385         g_hash_table_foreach(op->params, env_setter, NULL);
386     }
387 
388     if (env_setter == NULL || env_setter == set_alert_env) {
389         return;
390     }
391 
392     set_ocf_env("OCF_RA_VERSION_MAJOR", "1", NULL);
393     set_ocf_env("OCF_RA_VERSION_MINOR", "0", NULL);
394     set_ocf_env("OCF_ROOT", OCF_ROOT_DIR, NULL);
395     set_ocf_env("OCF_EXIT_REASON_PREFIX", PCMK_OCF_REASON_PREFIX, NULL);
396 
397     if (op->rsc) {
398         set_ocf_env("OCF_RESOURCE_INSTANCE", op->rsc, NULL);
399     }
400 
401     if (op->agent != NULL) {
402         set_ocf_env("OCF_RESOURCE_TYPE", op->agent, NULL);
403     }
404 
405     /* Notes: this is not added to specification yet. Sept 10,2004 */
406     if (op->provider != NULL) {
407         set_ocf_env("OCF_RESOURCE_PROVIDER", op->provider, NULL);
408     }
409 }
410 
411 static void
pipe_in_single_parameter(gpointer key,gpointer value,gpointer user_data)412 pipe_in_single_parameter(gpointer key, gpointer value, gpointer user_data)
413 {
414     svc_action_t *op = user_data;
415     char *buffer = crm_strdup_printf("%s=%s\n", (char *)key, (char *) value);
416     int ret, total = 0, len = strlen(buffer);
417 
418     do {
419         errno = 0;
420         ret = write(op->opaque->stdin_fd, buffer + total, len - total);
421         if (ret > 0) {
422             total += ret;
423         }
424 
425     } while ((errno == EINTR) && (total < len));
426     free(buffer);
427 }
428 
429 /*!
430  * \internal
431  * \brief Pipe parameters in via stdin for action
432  *
433  * \param[in] op  Action to use
434  */
435 static void
pipe_in_action_stdin_parameters(const svc_action_t * op)436 pipe_in_action_stdin_parameters(const svc_action_t *op)
437 {
438     crm_debug("sending args");
439     if (op->params) {
440         g_hash_table_foreach(op->params, pipe_in_single_parameter, (gpointer) op);
441     }
442 }
443 
444 gboolean
recurring_action_timer(gpointer data)445 recurring_action_timer(gpointer data)
446 {
447     svc_action_t *op = data;
448 
449     crm_debug("Scheduling another invocation of %s", op->id);
450 
451     /* Clean out the old result */
452     free(op->stdout_data);
453     op->stdout_data = NULL;
454     free(op->stderr_data);
455     op->stderr_data = NULL;
456     op->opaque->repeat_timer = 0;
457 
458     services_action_async(op, NULL);
459     return FALSE;
460 }
461 
462 /* Returns FALSE if 'op' should be free'd by the caller */
463 gboolean
operation_finalize(svc_action_t * op)464 operation_finalize(svc_action_t * op)
465 {
466     int recurring = 0;
467 
468     if (op->interval) {
469         if (op->cancel) {
470             op->status = PCMK_LRM_OP_CANCELLED;
471             cancel_recurring_action(op);
472         } else {
473             recurring = 1;
474             op->opaque->repeat_timer = g_timeout_add(op->interval,
475                                                      recurring_action_timer, (void *)op);
476         }
477     }
478 
479     if (op->opaque->callback) {
480         op->opaque->callback(op);
481     }
482 
483     op->pid = 0;
484 
485     services_untrack_op(op);
486 
487     if (!recurring && op->synchronous == FALSE) {
488         /*
489          * If this is a recurring action, do not free explicitly.
490          * It will get freed whenever the action gets cancelled.
491          */
492         services_action_free(op);
493         return TRUE;
494     }
495 
496     services_action_cleanup(op);
497     return FALSE;
498 }
499 
500 static void
operation_finished(mainloop_child_t * p,pid_t pid,int core,int signo,int exitcode)501 operation_finished(mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode)
502 {
503     svc_action_t *op = mainloop_child_userdata(p);
504     char *prefix = crm_strdup_printf("%s:%d", op->id, op->pid);
505 
506     mainloop_clear_child_userdata(p);
507     op->status = PCMK_LRM_OP_DONE;
508     CRM_ASSERT(op->pid == pid);
509 
510     crm_trace("%s %p %p", prefix, op->opaque->stderr_gsource, op->opaque->stdout_gsource);
511     if (op->opaque->stderr_gsource) {
512         /* Make sure we have read everything from the buffer.
513          * Depending on the priority mainloop gives the fd, operation_finished
514          * could occur before all the reads are done.  Force the read now.*/
515         crm_trace("%s dispatching stderr", prefix);
516         dispatch_stderr(op);
517         crm_trace("%s: %p", op->id, op->stderr_data);
518         mainloop_del_fd(op->opaque->stderr_gsource);
519         op->opaque->stderr_gsource = NULL;
520     }
521 
522     if (op->opaque->stdout_gsource) {
523         /* Make sure we have read everything from the buffer.
524          * Depending on the priority mainloop gives the fd, operation_finished
525          * could occur before all the reads are done.  Force the read now.*/
526         crm_trace("%s dispatching stdout", prefix);
527         dispatch_stdout(op);
528         crm_trace("%s: %p", op->id, op->stdout_data);
529         mainloop_del_fd(op->opaque->stdout_gsource);
530         op->opaque->stdout_gsource = NULL;
531     }
532 
533     if (op->opaque->stdin_fd >= 0) {
534         close(op->opaque->stdin_fd);
535     }
536 
537     if (signo) {
538         if (mainloop_child_timeout(p)) {
539             crm_warn("%s - timed out after %dms", prefix, op->timeout);
540             op->status = PCMK_LRM_OP_TIMEOUT;
541             op->rc = PCMK_OCF_TIMEOUT;
542 
543         } else if (op->cancel) {
544             /* If an in-flight recurring operation was killed because it was
545              * cancelled, don't treat that as a failure.
546              */
547             crm_info("%s - terminated with signal %d", prefix, signo);
548             op->status = PCMK_LRM_OP_CANCELLED;
549             op->rc = PCMK_OCF_OK;
550 
551         } else {
552             crm_warn("%s - terminated with signal %d", prefix, signo);
553             op->status = PCMK_LRM_OP_ERROR;
554             op->rc = PCMK_OCF_SIGNAL;
555         }
556 
557     } else {
558         op->rc = exitcode;
559         crm_debug("%s - exited with rc=%d", prefix, exitcode);
560     }
561 
562     free(prefix);
563     prefix = crm_strdup_printf("%s:%d:stderr", op->id, op->pid);
564     crm_log_output(LOG_NOTICE, prefix, op->stderr_data);
565 
566     free(prefix);
567     prefix = crm_strdup_printf("%s:%d:stdout", op->id, op->pid);
568     crm_log_output(LOG_DEBUG, prefix, op->stdout_data);
569 
570     free(prefix);
571     operation_finalize(op);
572 }
573 
574 /*!
575  * \internal
576  * \brief Set operation rc and status per errno from stat(), fork() or execvp()
577  *
578  * \param[in,out] op     Operation to set rc and status for
579  * \param[in]     error  Value of errno after system call
580  *
581  * \return void
582  */
583 static void
services_handle_exec_error(svc_action_t * op,int error)584 services_handle_exec_error(svc_action_t * op, int error)
585 {
586     int rc_not_installed, rc_insufficient_priv, rc_exec_error;
587 
588     /* Mimic the return codes for each standard as that's what we'll convert back from in get_uniform_rc() */
589     if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_LSB)
590         && safe_str_eq(op->action, "status")) {
591 
592         rc_not_installed = PCMK_LSB_STATUS_NOT_INSTALLED;
593         rc_insufficient_priv = PCMK_LSB_STATUS_INSUFFICIENT_PRIV;
594         rc_exec_error = PCMK_LSB_STATUS_UNKNOWN;
595 
596 #if SUPPORT_NAGIOS
597     } else if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_NAGIOS)) {
598         rc_not_installed = NAGIOS_NOT_INSTALLED;
599         rc_insufficient_priv = NAGIOS_INSUFFICIENT_PRIV;
600         rc_exec_error = PCMK_OCF_EXEC_ERROR;
601 #endif
602 
603     } else {
604         rc_not_installed = PCMK_OCF_NOT_INSTALLED;
605         rc_insufficient_priv = PCMK_OCF_INSUFFICIENT_PRIV;
606         rc_exec_error = PCMK_OCF_EXEC_ERROR;
607     }
608 
609     switch (error) {   /* see execve(2), stat(2) and fork(2) */
610         case ENOENT:   /* No such file or directory */
611         case EISDIR:   /* Is a directory */
612         case ENOTDIR:  /* Path component is not a directory */
613         case EINVAL:   /* Invalid executable format */
614         case ENOEXEC:  /* Invalid executable format */
615             op->rc = rc_not_installed;
616             op->status = PCMK_LRM_OP_NOT_INSTALLED;
617             break;
618         case EACCES:   /* permission denied (various errors) */
619         case EPERM:    /* permission denied (various errors) */
620             op->rc = rc_insufficient_priv;
621             op->status = PCMK_LRM_OP_ERROR;
622             break;
623         default:
624             op->rc = rc_exec_error;
625             op->status = PCMK_LRM_OP_ERROR;
626     }
627 }
628 
629 static void
action_launch_child(svc_action_t * op)630 action_launch_child(svc_action_t *op)
631 {
632     /* SIGPIPE is ignored (which is different from signal blocking) by the gnutls library.
633      * Depending on the libqb version in use, libqb may set SIGPIPE to be ignored as well.
634      * We do not want this to be inherited by the child process. By resetting this the signal
635      * to the default behavior, we avoid some potential odd problems that occur during OCF
636      * scripts when SIGPIPE is ignored by the environment. */
637     signal(SIGPIPE, SIG_DFL);
638 
639 #if defined(HAVE_SCHED_SETSCHEDULER)
640     if (sched_getscheduler(0) != SCHED_OTHER) {
641         struct sched_param sp;
642 
643         memset(&sp, 0, sizeof(sp));
644         sp.sched_priority = 0;
645 
646         if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
647             crm_perror(LOG_ERR, "Could not reset scheduling policy to SCHED_OTHER for %s", op->id);
648         }
649     }
650 #endif
651     if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
652         crm_perror(LOG_ERR, "Could not reset process priority to 0 for %s", op->id);
653     }
654 
655     /* Man: The call setpgrp() is equivalent to setpgid(0,0)
656      * _and_ compiles on BSD variants too
657      * need to investigate if it works the same too.
658      */
659     setpgid(0, 0);
660 
661     pcmk__close_fds_in_child(false);
662 
663 #if SUPPORT_CIBSECRETS
664     if (replace_secret_params(op->rsc, op->params) < 0) {
665         /* replacing secrets failed! */
666         if (safe_str_eq(op->action,"stop")) {
667             /* don't fail on stop! */
668             crm_info("proceeding with the stop operation for %s", op->rsc);
669 
670         } else {
671             crm_err("failed to get secrets for %s, "
672                     "considering resource not configured", op->rsc);
673             _exit(PCMK_OCF_NOT_CONFIGURED);
674         }
675     }
676 #endif
677 
678     add_action_env_vars(op);
679 
680     /* Become the desired user */
681     if (op->opaque->uid && (geteuid() == 0)) {
682         if (op->opaque->gid && (setgid(op->opaque->gid) < 0)) {
683             crm_perror(LOG_ERR, "setting group to %d", op->opaque->gid);
684             _exit(PCMK_OCF_NOT_CONFIGURED);
685         }
686         if (setuid(op->opaque->uid) < 0) {
687             crm_perror(LOG_ERR, "setting user to %d", op->opaque->uid);
688             _exit(PCMK_OCF_NOT_CONFIGURED);
689         }
690         /* We could do initgroups() here if we kept a copy of the username */
691     }
692 
693     /* execute the RA */
694     execvp(op->opaque->exec, op->opaque->args);
695 
696     /* Most cases should have been already handled by stat() */
697     services_handle_exec_error(op, errno);
698 
699     _exit(op->rc);
700 }
701 
702 static void
action_synced_wait(svc_action_t * op,struct sigchld_data_s * data)703 action_synced_wait(svc_action_t *op, struct sigchld_data_s *data)
704 {
705     int status = 0;
706     int timeout = op->timeout;
707     time_t start = -1;
708     struct pollfd fds[3];
709     int wait_rc = 0;
710 
711     fds[0].fd = op->opaque->stdout_fd;
712     fds[0].events = POLLIN;
713     fds[0].revents = 0;
714 
715     fds[1].fd = op->opaque->stderr_fd;
716     fds[1].events = POLLIN;
717     fds[1].revents = 0;
718 
719     fds[2].fd = sigchld_open(data);
720     fds[2].events = POLLIN;
721     fds[2].revents = 0;
722 
723     crm_trace("Waiting for %d", op->pid);
724     start = time(NULL);
725     do {
726         int poll_rc = poll(fds, 3, timeout);
727 
728         if (poll_rc > 0) {
729             if (fds[0].revents & POLLIN) {
730                 svc_read_output(op->opaque->stdout_fd, op, FALSE);
731             }
732 
733             if (fds[1].revents & POLLIN) {
734                 svc_read_output(op->opaque->stderr_fd, op, TRUE);
735             }
736 
737             if ((fds[2].revents & POLLIN) && sigchld_received(fds[2].fd)) {
738                 wait_rc = waitpid(op->pid, &status, WNOHANG);
739 
740                 if (wait_rc > 0) {
741                     break;
742 
743                 } else if (wait_rc < 0) {
744                     if (errno == ECHILD) {
745                             /* Here, don't dare to kill and bail out... */
746                             break;
747 
748                     } else {
749                             /* ...otherwise pretend process still runs. */
750                             wait_rc = 0;
751                     }
752                     crm_perror(LOG_ERR, "waitpid() for %d failed", op->pid);
753                 }
754             }
755 
756         } else if (poll_rc == 0) {
757             timeout = 0;
758             break;
759 
760         } else if (poll_rc < 0) {
761             if (errno != EINTR) {
762                 crm_perror(LOG_ERR, "poll() failed");
763                 break;
764             }
765         }
766 
767         timeout = op->timeout - (time(NULL) - start) * 1000;
768 
769     } while ((op->timeout < 0 || timeout > 0));
770 
771     crm_trace("Child done: %d", op->pid);
772     if (wait_rc <= 0) {
773         op->rc = PCMK_OCF_UNKNOWN_ERROR;
774 
775         if (op->timeout > 0 && timeout <= 0) {
776             op->status = PCMK_LRM_OP_TIMEOUT;
777             crm_warn("%s:%d - timed out after %dms", op->id, op->pid, op->timeout);
778 
779         } else {
780             op->status = PCMK_LRM_OP_ERROR;
781         }
782 
783         /* If only child hasn't been successfully waited for, yet.
784            This is to limit killing wrong target a bit more. */
785         if (wait_rc == 0 && waitpid(op->pid, &status, WNOHANG) == 0) {
786             if (kill(op->pid, SIGKILL)) {
787                 crm_err("kill(%d, KILL) failed: %d", op->pid, errno);
788             }
789             /* Safe to skip WNOHANG here as we sent non-ignorable signal. */
790             while (waitpid(op->pid, &status, 0) == (pid_t) -1 && errno == EINTR) /*omit*/;
791         }
792 
793     } else if (WIFEXITED(status)) {
794         op->status = PCMK_LRM_OP_DONE;
795         op->rc = WEXITSTATUS(status);
796         crm_info("Managed %s process %d exited with rc=%d", op->id, op->pid, op->rc);
797 
798     } else if (WIFSIGNALED(status)) {
799         int signo = WTERMSIG(status);
800 
801         op->status = PCMK_LRM_OP_ERROR;
802         crm_err("Managed %s process %d exited with signal=%d", op->id, op->pid, signo);
803     }
804 #ifdef WCOREDUMP
805     if (WCOREDUMP(status)) {
806         crm_err("Managed %s process %d dumped core", op->id, op->pid);
807     }
808 #endif
809 
810     svc_read_output(op->opaque->stdout_fd, op, FALSE);
811     svc_read_output(op->opaque->stderr_fd, op, TRUE);
812 
813     close(op->opaque->stdout_fd);
814     close(op->opaque->stderr_fd);
815     if (op->opaque->stdin_fd >= 0) {
816         close(op->opaque->stdin_fd);
817     }
818     sigchld_close(fds[2].fd);
819 }
820 
821 /* For an asynchronous 'op', returns FALSE if 'op' should be free'd by the caller */
822 /* For a synchronous 'op', returns FALSE if 'op' fails */
823 gboolean
services_os_action_execute(svc_action_t * op)824 services_os_action_execute(svc_action_t * op)
825 {
826     int stdout_fd[2];
827     int stderr_fd[2];
828     int stdin_fd[2] = {-1, -1};
829     int rc;
830     struct stat st;
831     struct sigchld_data_s data;
832 
833     /* Fail fast */
834     if(stat(op->opaque->exec, &st) != 0) {
835         rc = errno;
836         crm_warn("Cannot execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
837         services_handle_exec_error(op, rc);
838         if (!op->synchronous) {
839             return operation_finalize(op);
840         }
841         return FALSE;
842     }
843 
844     if (pipe(stdout_fd) < 0) {
845         rc = errno;
846 
847         crm_err("pipe(stdout_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
848 
849         services_handle_exec_error(op, rc);
850         if (!op->synchronous) {
851             return operation_finalize(op);
852         }
853         return FALSE;
854     }
855 
856     if (pipe(stderr_fd) < 0) {
857         rc = errno;
858 
859         close(stdout_fd[0]);
860         close(stdout_fd[1]);
861 
862         crm_err("pipe(stderr_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
863 
864         services_handle_exec_error(op, rc);
865         if (!op->synchronous) {
866             return operation_finalize(op);
867         }
868         return FALSE;
869     }
870 
871     if (safe_str_eq(op->standard, PCMK_RESOURCE_CLASS_STONITH)) {
872         if (pipe(stdin_fd) < 0) {
873             rc = errno;
874 
875             close(stdout_fd[0]);
876             close(stdout_fd[1]);
877             close(stderr_fd[0]);
878             close(stderr_fd[1]);
879 
880             crm_err("pipe(stdin_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
881 
882             services_handle_exec_error(op, rc);
883             if (!op->synchronous) {
884                 return operation_finalize(op);
885             }
886             return FALSE;
887         }
888     }
889 
890     if (op->synchronous) {
891         sigchld_setup(&data);
892     }
893 
894     op->pid = fork();
895     switch (op->pid) {
896         case -1:
897             rc = errno;
898 
899             close(stdout_fd[0]);
900             close(stdout_fd[1]);
901             close(stderr_fd[0]);
902             close(stderr_fd[1]);
903             if (stdin_fd[0] >= 0) {
904                 close(stdin_fd[0]);
905                 close(stdin_fd[1]);
906             }
907 
908             crm_err("Could not execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc);
909             services_handle_exec_error(op, rc);
910             if (!op->synchronous) {
911                 return operation_finalize(op);
912             }
913 
914             sigchld_cleanup(&data);
915             return FALSE;
916 
917         case 0:                /* Child */
918             close(stdout_fd[0]);
919             close(stderr_fd[0]);
920             if (stdin_fd[1] >= 0) {
921                 close(stdin_fd[1]);
922             }
923             if (STDOUT_FILENO != stdout_fd[1]) {
924                 if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
925                     crm_err("dup2() failed (stdout)");
926                 }
927                 close(stdout_fd[1]);
928             }
929             if (STDERR_FILENO != stderr_fd[1]) {
930                 if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
931                     crm_err("dup2() failed (stderr)");
932                 }
933                 close(stderr_fd[1]);
934             }
935             if ((stdin_fd[0] >= 0) &&
936                 (STDIN_FILENO != stdin_fd[0])) {
937                 if (dup2(stdin_fd[0], STDIN_FILENO) != STDIN_FILENO) {
938                     crm_err("dup2() failed (stdin)");
939                 }
940                 close(stdin_fd[0]);
941             }
942 
943             if (op->synchronous) {
944                 sigchld_cleanup(&data);
945             }
946 
947             action_launch_child(op);
948             CRM_ASSERT(0);  /* action_launch_child is effectively noreturn */
949     }
950 
951     /* Only the parent reaches here */
952     close(stdout_fd[1]);
953     close(stderr_fd[1]);
954     if (stdin_fd[0] >= 0) {
955         close(stdin_fd[0]);
956     }
957 
958     op->opaque->stdout_fd = stdout_fd[0];
959     rc = crm_set_nonblocking(op->opaque->stdout_fd);
960     if (rc < 0) {
961         crm_warn("Could not set child output non-blocking: %s "
962                  CRM_XS " rc=%d",
963                  pcmk_strerror(rc), rc);
964     }
965 
966     op->opaque->stderr_fd = stderr_fd[0];
967     rc = crm_set_nonblocking(op->opaque->stderr_fd);
968     if (rc < 0) {
969         crm_warn("Could not set child error output non-blocking: %s "
970                  CRM_XS " rc=%d",
971                  pcmk_strerror(rc), rc);
972     }
973 
974     op->opaque->stdin_fd = stdin_fd[1];
975     if (op->opaque->stdin_fd >= 0) {
976         // using buffer behind non-blocking-fd here - that could be improved
977         // as long as no other standard uses stdin_fd assume stonith
978         rc = crm_set_nonblocking(op->opaque->stdin_fd);
979         if (rc < 0) {
980             crm_warn("Could not set child input non-blocking: %s "
981                     CRM_XS " fd=%d,rc=%d",
982                     pcmk_strerror(rc), op->opaque->stdin_fd, rc);
983         }
984         pipe_in_action_stdin_parameters(op);
985         // as long as we are handling parameters directly in here just close
986         close(op->opaque->stdin_fd);
987         op->opaque->stdin_fd = -1;
988     }
989 
990     // after fds are setup properly and before we plug anything into mainloop
991     if (op->opaque->fork_callback) {
992         op->opaque->fork_callback(op);
993     }
994 
995     if (op->synchronous) {
996         action_synced_wait(op, &data);
997         sigchld_cleanup(&data);
998     } else {
999 
1000         crm_trace("Async waiting for %d - %s", op->pid, op->opaque->exec);
1001         mainloop_child_add_with_flags(op->pid,
1002                                       op->timeout,
1003                                       op->id,
1004                                       op,
1005                                       (op->flags & SVC_ACTION_LEAVE_GROUP) ? mainloop_leave_pid_group : 0,
1006                                       operation_finished);
1007 
1008 
1009         op->opaque->stdout_gsource = mainloop_add_fd(op->id,
1010                                                      G_PRIORITY_LOW,
1011                                                      op->opaque->stdout_fd, op, &stdout_callbacks);
1012 
1013         op->opaque->stderr_gsource = mainloop_add_fd(op->id,
1014                                                      G_PRIORITY_LOW,
1015                                                      op->opaque->stderr_fd, op, &stderr_callbacks);
1016 
1017         services_add_inflight_op(op);
1018     }
1019 
1020     return TRUE;
1021 }
1022 
1023 GList *
services_os_get_directory_list(const char * root,gboolean files,gboolean executable)1024 services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
1025 {
1026     GList *list = NULL;
1027     struct dirent **namelist;
1028     int entries = 0, lpc = 0;
1029     char buffer[PATH_MAX];
1030 
1031     entries = scandir(root, &namelist, NULL, alphasort);
1032     if (entries <= 0) {
1033         return list;
1034     }
1035 
1036     for (lpc = 0; lpc < entries; lpc++) {
1037         struct stat sb;
1038 
1039         if ('.' == namelist[lpc]->d_name[0]) {
1040             free(namelist[lpc]);
1041             continue;
1042         }
1043 
1044         snprintf(buffer, sizeof(buffer), "%s/%s", root, namelist[lpc]->d_name);
1045 
1046         if (stat(buffer, &sb)) {
1047             continue;
1048         }
1049 
1050         if (S_ISDIR(sb.st_mode)) {
1051             if (files) {
1052                 free(namelist[lpc]);
1053                 continue;
1054             }
1055 
1056         } else if (S_ISREG(sb.st_mode)) {
1057             if (files == FALSE) {
1058                 free(namelist[lpc]);
1059                 continue;
1060 
1061             } else if (executable
1062                        && (sb.st_mode & S_IXUSR) == 0
1063                        && (sb.st_mode & S_IXGRP) == 0 && (sb.st_mode & S_IXOTH) == 0) {
1064                 free(namelist[lpc]);
1065                 continue;
1066             }
1067         }
1068 
1069         list = g_list_append(list, strdup(namelist[lpc]->d_name));
1070 
1071         free(namelist[lpc]);
1072     }
1073 
1074     free(namelist);
1075     return list;
1076 }
1077 
1078 GList *
resources_os_list_lsb_agents(void)1079 resources_os_list_lsb_agents(void)
1080 {
1081     return get_directory_list(LSB_ROOT_DIR, TRUE, TRUE);
1082 }
1083 
1084 GList *
resources_os_list_ocf_providers(void)1085 resources_os_list_ocf_providers(void)
1086 {
1087     return get_directory_list(OCF_ROOT_DIR "/resource.d", FALSE, TRUE);
1088 }
1089 
1090 GList *
resources_os_list_ocf_agents(const char * provider)1091 resources_os_list_ocf_agents(const char *provider)
1092 {
1093     GList *gIter = NULL;
1094     GList *result = NULL;
1095     GList *providers = NULL;
1096 
1097     if (provider) {
1098         char buffer[500];
1099 
1100         snprintf(buffer, sizeof(buffer), "%s/resource.d/%s", OCF_ROOT_DIR, provider);
1101         return get_directory_list(buffer, TRUE, TRUE);
1102     }
1103 
1104     providers = resources_os_list_ocf_providers();
1105     for (gIter = providers; gIter != NULL; gIter = gIter->next) {
1106         GList *tmp1 = result;
1107         GList *tmp2 = resources_os_list_ocf_agents(gIter->data);
1108 
1109         if (tmp2) {
1110             result = g_list_concat(tmp1, tmp2);
1111         }
1112     }
1113     g_list_free_full(providers, free);
1114     return result;
1115 }
1116 
1117 #if SUPPORT_NAGIOS
1118 GList *
resources_os_list_nagios_agents(void)1119 resources_os_list_nagios_agents(void)
1120 {
1121     GList *plugin_list = NULL;
1122     GList *result = NULL;
1123     GList *gIter = NULL;
1124 
1125     plugin_list = get_directory_list(NAGIOS_PLUGIN_DIR, TRUE, TRUE);
1126 
1127     /* Make sure both the plugin and its metadata exist */
1128     for (gIter = plugin_list; gIter != NULL; gIter = gIter->next) {
1129         const char *plugin = gIter->data;
1130         char *metadata = crm_strdup_printf(NAGIOS_METADATA_DIR "/%s.xml", plugin);
1131         struct stat st;
1132 
1133         if (stat(metadata, &st) == 0) {
1134             result = g_list_append(result, strdup(plugin));
1135         }
1136 
1137         free(metadata);
1138     }
1139     g_list_free_full(plugin_list, free);
1140     return result;
1141 }
1142 #endif
1143