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