This source file includes following definitions.
- sigchld_setup
- sigchld_open
- sigchld_close
- sigchld_received
- sigchld_cleanup
- sigchld_handler
- sigchld_setup
- sigchld_open
- sigchld_close
- sigchld_received
- sigchld_cleanup
- close_pipe
- svc_read_output
- dispatch_stdout
- dispatch_stderr
- pipe_out_done
- pipe_err_done
- set_ocf_env
- set_ocf_env_with_prefix
- set_alert_env
- add_action_env_vars
- pipe_in_single_parameter
- pipe_in_action_stdin_parameters
- recurring_action_timer
- services__finalize_async_op
- close_op_input
- finish_op_output
- log_op_output
- parse_exit_reason_from_stderr
- async_action_complete
- services__generic_error
- services__not_installed_error
- services__authorization_error
- services__configuration_error
- services__handle_exec_error
- exit_child
- action_launch_child
- wait_for_sync_result
- services__execute_file
- services_os_get_single_directory_list
- services_os_get_directory_list
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #ifndef _GNU_SOURCE
13 # define _GNU_SOURCE
14 #endif
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/wait.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <dirent.h>
22 #include <grp.h>
23 #include <string.h>
24 #include <sys/time.h>
25 #include <sys/resource.h>
26
27 #include "crm/crm.h"
28 #include "crm/common/mainloop.h"
29 #include "crm/services.h"
30 #include "crm/services_internal.h"
31
32 #include "services_private.h"
33
34 static void close_pipe(int fildes[]);
35
36
37
38
39
40
41
42
43
44 #ifdef HAVE_SYS_SIGNALFD_H
45
46
47
48 #include <sys/signalfd.h>
49
50
51 struct sigchld_data_s {
52 sigset_t mask;
53 sigset_t old_mask;
54 bool ignored;
55 };
56
57
58 static bool
59 sigchld_setup(struct sigchld_data_s *data)
60 {
61 sigemptyset(&(data->mask));
62 sigaddset(&(data->mask), SIGCHLD);
63
64 sigemptyset(&(data->old_mask));
65
66
67 if (sigprocmask(SIG_BLOCK, &(data->mask), &(data->old_mask)) < 0) {
68 crm_info("Wait for child process completion failed: %s "
69 CRM_XS " source=sigprocmask", pcmk_rc_str(errno));
70 return false;
71 }
72
73 data->ignored = false;
74
75 return true;
76 }
77
78
79 static int
80 sigchld_open(struct sigchld_data_s *data)
81 {
82 int fd;
83
84 CRM_CHECK(data != NULL, return -1);
85
86 fd = signalfd(-1, &(data->mask), SFD_NONBLOCK);
87 if (fd < 0) {
88 crm_info("Wait for child process completion failed: %s "
89 CRM_XS " source=signalfd", pcmk_rc_str(errno));
90 }
91 return fd;
92 }
93
94
95 static void
96 sigchld_close(int fd)
97 {
98 if (fd > 0) {
99 close(fd);
100 }
101 }
102
103
104 static bool
105 sigchld_received(int fd, int pid, struct sigchld_data_s *data)
106 {
107 struct signalfd_siginfo fdsi;
108 ssize_t s;
109
110 if (fd < 0) {
111 return false;
112 }
113 s = read(fd, &fdsi, sizeof(struct signalfd_siginfo));
114 if (s != sizeof(struct signalfd_siginfo)) {
115 crm_info("Wait for child process completion failed: %s "
116 CRM_XS " source=read", pcmk_rc_str(errno));
117
118 } else if (fdsi.ssi_signo == SIGCHLD) {
119 if (fdsi.ssi_pid == pid) {
120 return true;
121
122 } else {
123
124
125
126
127
128 data->ignored = true;
129 return false;
130 }
131 }
132 return false;
133 }
134
135
136 static void
137 sigchld_cleanup(struct sigchld_data_s *data)
138 {
139
140 if ((sigismember(&(data->old_mask), SIGCHLD) == 0)
141 && (sigprocmask(SIG_UNBLOCK, &(data->mask), NULL) < 0)) {
142 crm_warn("Could not clean up after child process completion: %s",
143 pcmk_rc_str(errno));
144 }
145
146
147 if (data->ignored && kill(getpid(), SIGCHLD) != 0) {
148 crm_warn("Could not resend ignored SIGCHLD to ourselves: %s",
149 pcmk_rc_str(errno));
150 }
151 }
152
153 #else
154
155
156
157 struct sigchld_data_s {
158 int pipe_fd[2];
159 struct sigaction sa;
160 struct sigaction old_sa;
161 bool ignored;
162 };
163
164
165 volatile struct sigchld_data_s *last_sigchld_data = NULL;
166
167 static void
168 sigchld_handler(void)
169 {
170
171 if ((last_sigchld_data != NULL)
172 && (last_sigchld_data->pipe_fd[1] >= 0)
173 && (write(last_sigchld_data->pipe_fd[1], "", 1) == -1)) {
174 crm_info("Wait for child process completion failed: %s "
175 CRM_XS " source=write", pcmk_rc_str(errno));
176 }
177 }
178
179 static bool
180 sigchld_setup(struct sigchld_data_s *data)
181 {
182 int rc;
183
184 data->pipe_fd[0] = data->pipe_fd[1] = -1;
185
186 if (pipe(data->pipe_fd) == -1) {
187 crm_info("Wait for child process completion failed: %s "
188 CRM_XS " source=pipe", pcmk_rc_str(errno));
189 return false;
190 }
191
192 rc = pcmk__set_nonblocking(data->pipe_fd[0]);
193 if (rc != pcmk_rc_ok) {
194 crm_info("Could not set pipe input non-blocking: %s " CRM_XS " rc=%d",
195 pcmk_rc_str(rc), rc);
196 }
197 rc = pcmk__set_nonblocking(data->pipe_fd[1]);
198 if (rc != pcmk_rc_ok) {
199 crm_info("Could not set pipe output non-blocking: %s " CRM_XS " rc=%d",
200 pcmk_rc_str(rc), rc);
201 }
202
203
204 data->sa.sa_handler = (sighandler_t) sigchld_handler;
205 data->sa.sa_flags = 0;
206 sigemptyset(&(data->sa.sa_mask));
207 if (sigaction(SIGCHLD, &(data->sa), &(data->old_sa)) < 0) {
208 crm_info("Wait for child process completion failed: %s "
209 CRM_XS " source=sigaction", pcmk_rc_str(errno));
210 }
211
212 data->ignored = false;
213
214
215 last_sigchld_data = data;
216 return true;
217 }
218
219 static int
220 sigchld_open(struct sigchld_data_s *data)
221 {
222 CRM_CHECK(data != NULL, return -1);
223 return data->pipe_fd[0];
224 }
225
226 static void
227 sigchld_close(int fd)
228 {
229
230 return;
231 }
232
233 static bool
234 sigchld_received(int fd, int pid, struct sigchld_data_s *data)
235 {
236 char ch;
237
238 if (fd < 0) {
239 return false;
240 }
241
242
243 while (read(fd, &ch, 1) == 1) ;
244 return true;
245 }
246
247 static void
248 sigchld_cleanup(struct sigchld_data_s *data)
249 {
250
251 if (sigaction(SIGCHLD, &(data->old_sa), NULL) < 0) {
252 crm_warn("Could not clean up after child process completion: %s",
253 pcmk_rc_str(errno));
254 }
255
256 close_pipe(data->pipe_fd);
257
258
259 if (data->ignored && kill(getpid(), SIGCHLD) != 0) {
260 crm_warn("Could not resend ignored SIGCHLD to ourselves: %s",
261 pcmk_rc_str(errno));
262 }
263 }
264
265 #endif
266
267
268
269
270
271
272
273 static void
274 close_pipe(int fildes[])
275 {
276 if (fildes[0] >= 0) {
277 close(fildes[0]);
278 fildes[0] = -1;
279 }
280 if (fildes[1] >= 0) {
281 close(fildes[1]);
282 fildes[1] = -1;
283 }
284 }
285
286 #define out_type(is_stderr) ((is_stderr)? "stderr" : "stdout")
287
288
289 #define MAX_OUTPUT (10 * 1024 * 1024)
290
291 static gboolean
292 svc_read_output(int fd, svc_action_t * op, bool is_stderr)
293 {
294 char *data = NULL;
295 ssize_t rc = 0;
296 size_t len = 0;
297 size_t discarded = 0;
298 char buf[500];
299 static const size_t buf_read_len = sizeof(buf) - 1;
300
301 if (fd < 0) {
302 crm_trace("No fd for %s", op->id);
303 return FALSE;
304 }
305
306 if (is_stderr && op->stderr_data) {
307 len = strlen(op->stderr_data);
308 data = op->stderr_data;
309 crm_trace("Reading %s stderr into offset %lld",
310 op->id, (long long) len);
311
312 } else if (is_stderr == FALSE && op->stdout_data) {
313 len = strlen(op->stdout_data);
314 data = op->stdout_data;
315 crm_trace("Reading %s stdout into offset %lld",
316 op->id, (long long) len);
317
318 } else {
319 crm_trace("Reading %s %s", op->id, out_type(is_stderr));
320 }
321
322 do {
323 errno = 0;
324 rc = read(fd, buf, buf_read_len);
325 if (rc > 0) {
326 if (len < MAX_OUTPUT) {
327 buf[rc] = 0;
328 crm_trace("Received %lld bytes of %s %s: %.80s",
329 (long long) rc, op->id, out_type(is_stderr), buf);
330 data = pcmk__realloc(data, len + rc + 1);
331 strcpy(data + len, buf);
332 len += rc;
333 } else {
334 discarded += rc;
335 }
336
337 } else if (errno != EINTR) {
338 rc = 0;
339 break;
340 }
341 } while ((rc == buf_read_len) || (rc < 0));
342
343 if (discarded > 0) {
344 crm_warn("Truncated %s %s to %lld bytes (discarded %lld)",
345 op->id, out_type(is_stderr), (long long) len,
346 (long long) discarded);
347 }
348
349 if (is_stderr) {
350 op->stderr_data = data;
351 } else {
352 op->stdout_data = data;
353 }
354
355 return rc != 0;
356 }
357
358 static int
359 dispatch_stdout(gpointer userdata)
360 {
361 svc_action_t *op = (svc_action_t *) userdata;
362
363 return svc_read_output(op->opaque->stdout_fd, op, FALSE);
364 }
365
366 static int
367 dispatch_stderr(gpointer userdata)
368 {
369 svc_action_t *op = (svc_action_t *) userdata;
370
371 return svc_read_output(op->opaque->stderr_fd, op, TRUE);
372 }
373
374 static void
375 pipe_out_done(gpointer user_data)
376 {
377 svc_action_t *op = (svc_action_t *) user_data;
378
379 crm_trace("%p", op);
380
381 op->opaque->stdout_gsource = NULL;
382 if (op->opaque->stdout_fd > STDOUT_FILENO) {
383 close(op->opaque->stdout_fd);
384 }
385 op->opaque->stdout_fd = -1;
386 }
387
388 static void
389 pipe_err_done(gpointer user_data)
390 {
391 svc_action_t *op = (svc_action_t *) user_data;
392
393 op->opaque->stderr_gsource = NULL;
394 if (op->opaque->stderr_fd > STDERR_FILENO) {
395 close(op->opaque->stderr_fd);
396 }
397 op->opaque->stderr_fd = -1;
398 }
399
400 static struct mainloop_fd_callbacks stdout_callbacks = {
401 .dispatch = dispatch_stdout,
402 .destroy = pipe_out_done,
403 };
404
405 static struct mainloop_fd_callbacks stderr_callbacks = {
406 .dispatch = dispatch_stderr,
407 .destroy = pipe_err_done,
408 };
409
410 static void
411 set_ocf_env(const char *key, const char *value, gpointer user_data)
412 {
413 if (setenv(key, value, 1) != 0) {
414 crm_perror(LOG_ERR, "setenv failed for key:%s and value:%s", key, value);
415 }
416 }
417
418 static void
419 set_ocf_env_with_prefix(gpointer key, gpointer value, gpointer user_data)
420 {
421 char buffer[500];
422
423 snprintf(buffer, sizeof(buffer), strcmp(key, "OCF_CHECK_LEVEL") != 0 ? "OCF_RESKEY_%s" : "%s", (char *)key);
424 set_ocf_env(buffer, value, user_data);
425 }
426
427 static void
428 set_alert_env(gpointer key, gpointer value, gpointer user_data)
429 {
430 int rc;
431
432 if (value != NULL) {
433 rc = setenv(key, value, 1);
434 } else {
435 rc = unsetenv(key);
436 }
437
438 if (rc < 0) {
439 crm_perror(LOG_ERR, "setenv %s=%s",
440 (char*)key, (value? (char*)value : ""));
441 } else {
442 crm_trace("setenv %s=%s", (char*)key, (value? (char*)value : ""));
443 }
444 }
445
446
447
448
449
450
451
452 static void
453 add_action_env_vars(const svc_action_t *op)
454 {
455 void (*env_setter)(gpointer, gpointer, gpointer) = NULL;
456 if (op->agent == NULL) {
457 env_setter = set_alert_env;
458
459 } else if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_OCF, pcmk__str_casei)) {
460 env_setter = set_ocf_env_with_prefix;
461 }
462
463 if (env_setter != NULL && op->params != NULL) {
464 g_hash_table_foreach(op->params, env_setter, NULL);
465 }
466
467 if (env_setter == NULL || env_setter == set_alert_env) {
468 return;
469 }
470
471 set_ocf_env("OCF_RA_VERSION_MAJOR", PCMK_OCF_MAJOR_VERSION, NULL);
472 set_ocf_env("OCF_RA_VERSION_MINOR", PCMK_OCF_MINOR_VERSION, NULL);
473 set_ocf_env("OCF_ROOT", OCF_ROOT_DIR, NULL);
474 set_ocf_env("OCF_EXIT_REASON_PREFIX", PCMK_OCF_REASON_PREFIX, NULL);
475
476 if (op->rsc) {
477 set_ocf_env("OCF_RESOURCE_INSTANCE", op->rsc, NULL);
478 }
479
480 if (op->agent != NULL) {
481 set_ocf_env("OCF_RESOURCE_TYPE", op->agent, NULL);
482 }
483
484
485 if (op->provider != NULL) {
486 set_ocf_env("OCF_RESOURCE_PROVIDER", op->provider, NULL);
487 }
488 }
489
490 static void
491 pipe_in_single_parameter(gpointer key, gpointer value, gpointer user_data)
492 {
493 svc_action_t *op = user_data;
494 char *buffer = crm_strdup_printf("%s=%s\n", (char *)key, (char *) value);
495 size_t len = strlen(buffer);
496 size_t total = 0;
497 ssize_t ret = 0;
498
499 do {
500 errno = 0;
501 ret = write(op->opaque->stdin_fd, buffer + total, len - total);
502 if (ret > 0) {
503 total += ret;
504 }
505 } while ((errno == EINTR) && (total < len));
506 free(buffer);
507 }
508
509
510
511
512
513
514
515 static void
516 pipe_in_action_stdin_parameters(const svc_action_t *op)
517 {
518 if (op->params) {
519 g_hash_table_foreach(op->params, pipe_in_single_parameter, (gpointer) op);
520 }
521 }
522
523 gboolean
524 recurring_action_timer(gpointer data)
525 {
526 svc_action_t *op = data;
527
528 crm_debug("Scheduling another invocation of %s", op->id);
529
530
531 free(op->stdout_data);
532 op->stdout_data = NULL;
533 free(op->stderr_data);
534 op->stderr_data = NULL;
535 op->opaque->repeat_timer = 0;
536
537 services_action_async(op, NULL);
538 return FALSE;
539 }
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559 int
560 services__finalize_async_op(svc_action_t *op)
561 {
562 CRM_CHECK((op != NULL) && !(op->synchronous), return EINVAL);
563
564 if (op->interval_ms != 0) {
565
566 if (op->cancel) {
567 services__set_cancelled(op);
568 cancel_recurring_action(op);
569 } else {
570 op->opaque->repeat_timer = g_timeout_add(op->interval_ms,
571 recurring_action_timer,
572 (void *) op);
573 }
574 }
575
576 if (op->opaque->callback != NULL) {
577 op->opaque->callback(op);
578 }
579
580
581 op->pid = 0;
582 services_untrack_op(op);
583
584 if ((op->interval_ms != 0) && !(op->cancel)) {
585
586 services_action_cleanup(op);
587 return EBUSY;
588 }
589
590 services_action_free(op);
591 return pcmk_rc_ok;
592 }
593
594 static void
595 close_op_input(svc_action_t *op)
596 {
597 if (op->opaque->stdin_fd >= 0) {
598 close(op->opaque->stdin_fd);
599 }
600 }
601
602 static void
603 finish_op_output(svc_action_t *op, bool is_stderr)
604 {
605 mainloop_io_t **source;
606 int fd;
607
608 if (is_stderr) {
609 source = &(op->opaque->stderr_gsource);
610 fd = op->opaque->stderr_fd;
611 } else {
612 source = &(op->opaque->stdout_gsource);
613 fd = op->opaque->stdout_fd;
614 }
615
616 if (op->synchronous || *source) {
617 crm_trace("Finish reading %s[%d] %s",
618 op->id, op->pid, (is_stderr? "stderr" : "stdout"));
619 svc_read_output(fd, op, is_stderr);
620 if (op->synchronous) {
621 close(fd);
622 } else {
623 mainloop_del_fd(*source);
624 *source = NULL;
625 }
626 }
627 }
628
629
630 static void
631 log_op_output(svc_action_t *op)
632 {
633 char *prefix = crm_strdup_printf("%s[%d] error output", op->id, op->pid);
634
635
636
637
638
639 crm_log_output(LOG_INFO, prefix, op->stderr_data);
640 strcpy(prefix + strlen(prefix) - strlen("error output"), "output");
641 crm_log_output(LOG_DEBUG, prefix, op->stdout_data);
642 free(prefix);
643 }
644
645
646 #define EXIT_REASON_MAX_LEN 128
647
648 static void
649 parse_exit_reason_from_stderr(svc_action_t *op)
650 {
651 const char *reason_start = NULL;
652 const char *reason_end = NULL;
653 const int prefix_len = strlen(PCMK_OCF_REASON_PREFIX);
654
655 if ((op->stderr_data == NULL) ||
656
657 !pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_OCF, pcmk__str_none)) {
658 return;
659 }
660
661
662 for (const char *cur = strstr(op->stderr_data, PCMK_OCF_REASON_PREFIX);
663 cur != NULL; cur = strstr(cur, PCMK_OCF_REASON_PREFIX)) {
664
665 cur += prefix_len;
666 reason_start = cur;
667 }
668
669 if ((reason_start == NULL) || (reason_start[0] == '\n')
670 || (reason_start[0] == '\0')) {
671 return;
672 }
673
674
675 reason_end = strchr(reason_start, '\n');
676 if (reason_end == NULL) {
677 reason_end = reason_start + strlen(reason_start);
678 }
679
680
681 if (reason_end > (reason_start + EXIT_REASON_MAX_LEN)) {
682 reason_end = reason_start + EXIT_REASON_MAX_LEN;
683 }
684
685 free(op->opaque->exit_reason);
686 op->opaque->exit_reason = strndup(reason_start, reason_end - reason_start);
687 }
688
689
690
691
692
693
694
695
696
697
698
699 static void
700 async_action_complete(mainloop_child_t *p, pid_t pid, int core, int signo,
701 int exitcode)
702 {
703 svc_action_t *op = mainloop_child_userdata(p);
704
705 mainloop_clear_child_userdata(p);
706 CRM_CHECK(op->pid == pid,
707 services__set_result(op, services__generic_error(op),
708 PCMK_EXEC_ERROR, "Bug in mainloop handling");
709 return);
710
711
712
713
714
715 finish_op_output(op, true);
716 finish_op_output(op, false);
717
718 close_op_input(op);
719
720 if (signo == 0) {
721 crm_debug("%s[%d] exited with status %d", op->id, op->pid, exitcode);
722 services__set_result(op, exitcode, PCMK_EXEC_DONE, NULL);
723 log_op_output(op);
724 parse_exit_reason_from_stderr(op);
725
726 } else if (mainloop_child_timeout(p)) {
727 const char *kind = services__action_kind(op);
728
729 crm_info("%s %s[%d] timed out after %s",
730 kind, op->id, op->pid, pcmk__readable_interval(op->timeout));
731 services__format_result(op, services__generic_error(op),
732 PCMK_EXEC_TIMEOUT,
733 "%s did not complete within %s",
734 kind, pcmk__readable_interval(op->timeout));
735
736 } else if (op->cancel) {
737
738
739
740 crm_info("%s[%d] terminated with signal %d (%s)",
741 op->id, op->pid, signo, strsignal(signo));
742 services__set_result(op, PCMK_OCF_OK, PCMK_EXEC_CANCELLED, NULL);
743
744 } else {
745 crm_info("%s[%d] terminated with signal %d (%s)",
746 op->id, op->pid, signo, strsignal(signo));
747 services__format_result(op, PCMK_OCF_UNKNOWN_ERROR, PCMK_EXEC_ERROR,
748 "%s interrupted by %s signal",
749 services__action_kind(op), strsignal(signo));
750 }
751
752 services__finalize_async_op(op);
753 }
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768 int
769 services__generic_error(const svc_action_t *op)
770 {
771 if ((op == NULL) || (op->standard == NULL)) {
772 return PCMK_OCF_UNKNOWN_ERROR;
773 }
774
775 #if PCMK__ENABLE_LSB
776 if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_LSB, pcmk__str_casei)
777 && pcmk__str_eq(op->action, PCMK_ACTION_STATUS, pcmk__str_casei)) {
778
779 return PCMK_LSB_STATUS_UNKNOWN;
780 }
781 #endif
782
783 #if SUPPORT_NAGIOS
784 if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_NAGIOS, pcmk__str_casei)) {
785 return NAGIOS_STATE_UNKNOWN;
786 }
787 #endif
788
789 return PCMK_OCF_UNKNOWN_ERROR;
790 }
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805 int
806 services__not_installed_error(const svc_action_t *op)
807 {
808 if ((op == NULL) || (op->standard == NULL)) {
809 return PCMK_OCF_UNKNOWN_ERROR;
810 }
811
812 #if PCMK__ENABLE_LSB
813 if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_LSB, pcmk__str_casei)
814 && pcmk__str_eq(op->action, PCMK_ACTION_STATUS, pcmk__str_casei)) {
815
816 return PCMK_LSB_STATUS_NOT_INSTALLED;
817 }
818 #endif
819
820 #if SUPPORT_NAGIOS
821 if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_NAGIOS, pcmk__str_casei)) {
822 return NAGIOS_STATE_UNKNOWN;
823 }
824 #endif
825
826 return PCMK_OCF_NOT_INSTALLED;
827 }
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842 int
843 services__authorization_error(const svc_action_t *op)
844 {
845 if ((op == NULL) || (op->standard == NULL)) {
846 return PCMK_OCF_UNKNOWN_ERROR;
847 }
848
849 #if PCMK__ENABLE_LSB
850 if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_LSB, pcmk__str_casei)
851 && pcmk__str_eq(op->action, PCMK_ACTION_STATUS, pcmk__str_casei)) {
852
853 return PCMK_LSB_STATUS_INSUFFICIENT_PRIV;
854 }
855 #endif
856
857 #if SUPPORT_NAGIOS
858 if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_NAGIOS, pcmk__str_casei)) {
859 return NAGIOS_INSUFFICIENT_PRIV;
860 }
861 #endif
862
863 return PCMK_OCF_INSUFFICIENT_PRIV;
864 }
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880 int
881 services__configuration_error(const svc_action_t *op, bool is_fatal)
882 {
883 if ((op == NULL) || (op->standard == NULL)) {
884 return PCMK_OCF_UNKNOWN_ERROR;
885 }
886
887 #if PCMK__ENABLE_LSB
888 if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_LSB, pcmk__str_casei)
889 && pcmk__str_eq(op->action, PCMK_ACTION_STATUS, pcmk__str_casei)) {
890
891 return PCMK_LSB_NOT_CONFIGURED;
892 }
893 #endif
894
895 #if SUPPORT_NAGIOS
896 if (pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_NAGIOS, pcmk__str_casei)) {
897 return NAGIOS_STATE_UNKNOWN;
898 }
899 #endif
900
901 return is_fatal? PCMK_OCF_NOT_CONFIGURED : PCMK_OCF_INVALID_PARAM;
902 }
903
904
905
906
907
908
909
910
911
912
913
914 void
915 services__handle_exec_error(svc_action_t * op, int error)
916 {
917 const char *name = op->opaque->exec;
918
919 if (name == NULL) {
920 name = op->agent;
921 if (name == NULL) {
922 name = op->id;
923 }
924 }
925
926 switch (error) {
927 case ENOENT:
928 case EISDIR:
929 case ENOTDIR:
930 case EINVAL:
931 case ENOEXEC:
932 services__format_result(op, services__not_installed_error(op),
933 PCMK_EXEC_NOT_INSTALLED, "%s: %s",
934 name, pcmk_rc_str(error));
935 break;
936 case EACCES:
937 case EPERM:
938 services__format_result(op, services__authorization_error(op),
939 PCMK_EXEC_ERROR, "%s: %s",
940 name, pcmk_rc_str(error));
941 break;
942 default:
943 services__set_result(op, services__generic_error(op),
944 PCMK_EXEC_ERROR, pcmk_rc_str(error));
945 }
946 }
947
948
949
950
951
952
953
954
955
956 static void
957 exit_child(const svc_action_t *op, int exit_status, const char *exit_reason)
958 {
959 if ((op != NULL) && (exit_reason != NULL)
960 && pcmk__str_eq(op->standard, PCMK_RESOURCE_CLASS_OCF,
961 pcmk__str_none)) {
962 fprintf(stderr, PCMK_OCF_REASON_PREFIX "%s\n", exit_reason);
963 }
964 _exit(exit_status);
965 }
966
967 static void
968 action_launch_child(svc_action_t *op)
969 {
970 int rc;
971
972
973
974
975
976
977 signal(SIGPIPE, SIG_DFL);
978
979 #if defined(HAVE_SCHED_SETSCHEDULER)
980 if (sched_getscheduler(0) != SCHED_OTHER) {
981 struct sched_param sp;
982
983 memset(&sp, 0, sizeof(sp));
984 sp.sched_priority = 0;
985
986 if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) {
987 crm_info("Could not reset scheduling policy for %s", op->id);
988 }
989 }
990 #endif
991 if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
992 crm_info("Could not reset process priority for %s", op->id);
993 }
994
995
996
997
998
999 setpgid(0, 0);
1000
1001 pcmk__close_fds_in_child(false);
1002
1003
1004
1005
1006
1007
1008
1009
1010 #if SUPPORT_CIBSECRETS
1011 rc = pcmk__substitute_secrets(op->rsc, op->params);
1012 if (rc != pcmk_rc_ok) {
1013 if (pcmk__str_eq(op->action, PCMK_ACTION_STOP, pcmk__str_casei)) {
1014 crm_info("Proceeding with stop operation for %s "
1015 "despite being unable to load CIB secrets (%s)",
1016 op->rsc, pcmk_rc_str(rc));
1017 } else {
1018 crm_err("Considering %s unconfigured "
1019 "because unable to load CIB secrets: %s",
1020 op->rsc, pcmk_rc_str(rc));
1021 exit_child(op, services__configuration_error(op, false),
1022 "Unable to load CIB secrets");
1023 }
1024 }
1025 #endif
1026
1027 add_action_env_vars(op);
1028
1029
1030 if (op->opaque->uid && (geteuid() == 0)) {
1031
1032
1033 if (op->opaque->gid && (setgid(op->opaque->gid) < 0)) {
1034 crm_err("Considering %s unauthorized because could not set "
1035 "child group to %d: %s",
1036 op->id, op->opaque->gid, strerror(errno));
1037 exit_child(op, services__authorization_error(op),
1038 "Could not set group for child process");
1039 }
1040
1041
1042
1043 if (setgroups(0, NULL) < 0) {
1044 crm_err("Considering %s unauthorized because could not "
1045 "clear supplementary groups: %s", op->id, strerror(errno));
1046 exit_child(op, services__authorization_error(op),
1047 "Could not clear supplementary groups for child process");
1048 }
1049
1050
1051 if (setuid(op->opaque->uid) < 0) {
1052 crm_err("Considering %s unauthorized because could not set user "
1053 "to %d: %s", op->id, op->opaque->uid, strerror(errno));
1054 exit_child(op, services__authorization_error(op),
1055 "Could not set user for child process");
1056 }
1057 }
1058
1059
1060 execvp(op->opaque->exec, op->opaque->args);
1061
1062
1063 rc = errno;
1064 services__handle_exec_error(op, rc);
1065 crm_err("Unable to execute %s: %s", op->id, strerror(rc));
1066 exit_child(op, op->rc, "Child process was unable to execute file");
1067 }
1068
1069
1070
1071
1072
1073
1074
1075
1076 static void
1077 wait_for_sync_result(svc_action_t *op, struct sigchld_data_s *data)
1078 {
1079 int status = 0;
1080 int timeout = op->timeout;
1081 time_t start = time(NULL);
1082 struct pollfd fds[3];
1083 int wait_rc = 0;
1084 const char *wait_reason = NULL;
1085
1086 fds[0].fd = op->opaque->stdout_fd;
1087 fds[0].events = POLLIN;
1088 fds[0].revents = 0;
1089
1090 fds[1].fd = op->opaque->stderr_fd;
1091 fds[1].events = POLLIN;
1092 fds[1].revents = 0;
1093
1094 fds[2].fd = sigchld_open(data);
1095 fds[2].events = POLLIN;
1096 fds[2].revents = 0;
1097
1098 crm_trace("Waiting for %s[%d]", op->id, op->pid);
1099 do {
1100 int poll_rc = poll(fds, 3, timeout);
1101
1102 wait_reason = NULL;
1103
1104 if (poll_rc > 0) {
1105 if (fds[0].revents & POLLIN) {
1106 svc_read_output(op->opaque->stdout_fd, op, FALSE);
1107 }
1108
1109 if (fds[1].revents & POLLIN) {
1110 svc_read_output(op->opaque->stderr_fd, op, TRUE);
1111 }
1112
1113 if ((fds[2].revents & POLLIN)
1114 && sigchld_received(fds[2].fd, op->pid, data)) {
1115 wait_rc = waitpid(op->pid, &status, WNOHANG);
1116
1117 if ((wait_rc > 0) || ((wait_rc < 0) && (errno == ECHILD))) {
1118
1119 break;
1120
1121 } else if (wait_rc < 0) {
1122 wait_reason = pcmk_rc_str(errno);
1123 crm_info("Wait for completion of %s[%d] failed: %s "
1124 CRM_XS " source=waitpid",
1125 op->id, op->pid, wait_reason);
1126 wait_rc = 0;
1127
1128 #ifndef HAVE_SYS_SIGNALFD_H
1129 } else {
1130
1131
1132
1133
1134
1135
1136 data->ignored = true;
1137 #endif
1138 }
1139 }
1140
1141 } else if (poll_rc == 0) {
1142
1143 timeout = 0;
1144 break;
1145
1146 } else if ((poll_rc < 0) && (errno != EINTR)) {
1147 wait_reason = pcmk_rc_str(errno);
1148 crm_info("Wait for completion of %s[%d] failed: %s "
1149 CRM_XS " source=poll", op->id, op->pid, wait_reason);
1150 break;
1151 }
1152
1153 timeout = op->timeout - (time(NULL) - start) * 1000;
1154
1155 } while ((op->timeout < 0 || timeout > 0));
1156
1157 crm_trace("Stopped waiting for %s[%d]", op->id, op->pid);
1158 finish_op_output(op, true);
1159 finish_op_output(op, false);
1160 close_op_input(op);
1161 sigchld_close(fds[2].fd);
1162
1163 if (wait_rc <= 0) {
1164
1165 if ((op->timeout > 0) && (timeout <= 0)) {
1166 services__format_result(op, services__generic_error(op),
1167 PCMK_EXEC_TIMEOUT,
1168 "%s did not exit within specified timeout",
1169 services__action_kind(op));
1170 crm_info("%s[%d] timed out after %dms",
1171 op->id, op->pid, op->timeout);
1172
1173 } else {
1174 services__set_result(op, services__generic_error(op),
1175 PCMK_EXEC_ERROR, wait_reason);
1176 }
1177
1178
1179
1180 if ((wait_rc == 0) && (waitpid(op->pid, &status, WNOHANG) == 0)) {
1181 if (kill(op->pid, SIGKILL)) {
1182 crm_warn("Could not kill rogue child %s[%d]: %s",
1183 op->id, op->pid, pcmk_rc_str(errno));
1184 }
1185
1186 while ((waitpid(op->pid, &status, 0) == (pid_t) -1)
1187 && (errno == EINTR)) {
1188 ;
1189 }
1190 }
1191
1192 } else if (WIFEXITED(status)) {
1193 services__set_result(op, WEXITSTATUS(status), PCMK_EXEC_DONE, NULL);
1194 parse_exit_reason_from_stderr(op);
1195 crm_info("%s[%d] exited with status %d", op->id, op->pid, op->rc);
1196
1197 } else if (WIFSIGNALED(status)) {
1198 int signo = WTERMSIG(status);
1199
1200 services__format_result(op, services__generic_error(op),
1201 PCMK_EXEC_ERROR, "%s interrupted by %s signal",
1202 services__action_kind(op), strsignal(signo));
1203 crm_info("%s[%d] terminated with signal %d (%s)",
1204 op->id, op->pid, signo, strsignal(signo));
1205
1206 #ifdef WCOREDUMP
1207 if (WCOREDUMP(status)) {
1208 crm_warn("%s[%d] dumped core", op->id, op->pid);
1209 }
1210 #endif
1211
1212 } else {
1213
1214 services__set_result(op, services__generic_error(op), PCMK_EXEC_ERROR,
1215 "Unable to wait for child to complete");
1216 }
1217 }
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235 int
1236 services__execute_file(svc_action_t *op)
1237 {
1238 int stdout_fd[2];
1239 int stderr_fd[2];
1240 int stdin_fd[2] = {-1, -1};
1241 int rc;
1242 struct stat st;
1243 struct sigchld_data_s data = { .ignored = false };
1244
1245
1246 if (stat(op->opaque->exec, &st) != 0) {
1247 rc = errno;
1248 crm_info("Cannot execute '%s': %s " CRM_XS " stat rc=%d",
1249 op->opaque->exec, pcmk_rc_str(rc), rc);
1250 services__handle_exec_error(op, rc);
1251 goto done;
1252 }
1253
1254 if (pipe(stdout_fd) < 0) {
1255 rc = errno;
1256 crm_info("Cannot execute '%s': %s " CRM_XS " pipe(stdout) rc=%d",
1257 op->opaque->exec, pcmk_rc_str(rc), rc);
1258 services__handle_exec_error(op, rc);
1259 goto done;
1260 }
1261
1262 if (pipe(stderr_fd) < 0) {
1263 rc = errno;
1264
1265 close_pipe(stdout_fd);
1266
1267 crm_info("Cannot execute '%s': %s " CRM_XS " pipe(stderr) rc=%d",
1268 op->opaque->exec, pcmk_rc_str(rc), rc);
1269 services__handle_exec_error(op, rc);
1270 goto done;
1271 }
1272
1273 if (pcmk_is_set(pcmk_get_ra_caps(op->standard), pcmk_ra_cap_stdin)) {
1274 if (pipe(stdin_fd) < 0) {
1275 rc = errno;
1276
1277 close_pipe(stdout_fd);
1278 close_pipe(stderr_fd);
1279
1280 crm_info("Cannot execute '%s': %s " CRM_XS " pipe(stdin) rc=%d",
1281 op->opaque->exec, pcmk_rc_str(rc), rc);
1282 services__handle_exec_error(op, rc);
1283 goto done;
1284 }
1285 }
1286
1287 if (op->synchronous && !sigchld_setup(&data)) {
1288 close_pipe(stdin_fd);
1289 close_pipe(stdout_fd);
1290 close_pipe(stderr_fd);
1291 sigchld_cleanup(&data);
1292 services__set_result(op, services__generic_error(op), PCMK_EXEC_ERROR,
1293 "Could not manage signals for child process");
1294 goto done;
1295 }
1296
1297 op->pid = fork();
1298 switch (op->pid) {
1299 case -1:
1300 rc = errno;
1301 close_pipe(stdin_fd);
1302 close_pipe(stdout_fd);
1303 close_pipe(stderr_fd);
1304
1305 crm_info("Cannot execute '%s': %s " CRM_XS " fork rc=%d",
1306 op->opaque->exec, pcmk_rc_str(rc), rc);
1307 services__handle_exec_error(op, rc);
1308 if (op->synchronous) {
1309 sigchld_cleanup(&data);
1310 }
1311 goto done;
1312 break;
1313
1314 case 0:
1315 close(stdout_fd[0]);
1316 close(stderr_fd[0]);
1317 if (stdin_fd[1] >= 0) {
1318 close(stdin_fd[1]);
1319 }
1320 if (STDOUT_FILENO != stdout_fd[1]) {
1321 if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1322 crm_warn("Can't redirect output from '%s': %s "
1323 CRM_XS " errno=%d",
1324 op->opaque->exec, pcmk_rc_str(errno), errno);
1325 }
1326 close(stdout_fd[1]);
1327 }
1328 if (STDERR_FILENO != stderr_fd[1]) {
1329 if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) {
1330 crm_warn("Can't redirect error output from '%s': %s "
1331 CRM_XS " errno=%d",
1332 op->opaque->exec, pcmk_rc_str(errno), errno);
1333 }
1334 close(stderr_fd[1]);
1335 }
1336 if ((stdin_fd[0] >= 0) &&
1337 (STDIN_FILENO != stdin_fd[0])) {
1338 if (dup2(stdin_fd[0], STDIN_FILENO) != STDIN_FILENO) {
1339 crm_warn("Can't redirect input to '%s': %s "
1340 CRM_XS " errno=%d",
1341 op->opaque->exec, pcmk_rc_str(errno), errno);
1342 }
1343 close(stdin_fd[0]);
1344 }
1345
1346 if (op->synchronous) {
1347 sigchld_cleanup(&data);
1348 }
1349
1350 action_launch_child(op);
1351 pcmk__assert(false);
1352 }
1353
1354
1355 close(stdout_fd[1]);
1356 close(stderr_fd[1]);
1357 if (stdin_fd[0] >= 0) {
1358 close(stdin_fd[0]);
1359 }
1360
1361 op->opaque->stdout_fd = stdout_fd[0];
1362 rc = pcmk__set_nonblocking(op->opaque->stdout_fd);
1363 if (rc != pcmk_rc_ok) {
1364 crm_info("Could not set '%s' output non-blocking: %s "
1365 CRM_XS " rc=%d",
1366 op->opaque->exec, pcmk_rc_str(rc), rc);
1367 }
1368
1369 op->opaque->stderr_fd = stderr_fd[0];
1370 rc = pcmk__set_nonblocking(op->opaque->stderr_fd);
1371 if (rc != pcmk_rc_ok) {
1372 crm_info("Could not set '%s' error output non-blocking: %s "
1373 CRM_XS " rc=%d",
1374 op->opaque->exec, pcmk_rc_str(rc), rc);
1375 }
1376
1377 op->opaque->stdin_fd = stdin_fd[1];
1378 if (op->opaque->stdin_fd >= 0) {
1379
1380
1381 rc = pcmk__set_nonblocking(op->opaque->stdin_fd);
1382 if (rc != pcmk_rc_ok) {
1383 crm_info("Could not set '%s' input non-blocking: %s "
1384 CRM_XS " fd=%d,rc=%d", op->opaque->exec,
1385 pcmk_rc_str(rc), op->opaque->stdin_fd, rc);
1386 }
1387 pipe_in_action_stdin_parameters(op);
1388
1389 close(op->opaque->stdin_fd);
1390 op->opaque->stdin_fd = -1;
1391 }
1392
1393
1394 if (op->opaque->fork_callback) {
1395 op->opaque->fork_callback(op);
1396 }
1397
1398 if (op->synchronous) {
1399 wait_for_sync_result(op, &data);
1400 sigchld_cleanup(&data);
1401 goto done;
1402 }
1403
1404 crm_trace("Waiting async for '%s'[%d]", op->opaque->exec, op->pid);
1405 mainloop_child_add_with_flags(op->pid, op->timeout, op->id, op,
1406 pcmk_is_set(op->flags, SVC_ACTION_LEAVE_GROUP)? mainloop_leave_pid_group : 0,
1407 async_action_complete);
1408
1409 op->opaque->stdout_gsource = mainloop_add_fd(op->id,
1410 G_PRIORITY_LOW,
1411 op->opaque->stdout_fd, op,
1412 &stdout_callbacks);
1413 op->opaque->stderr_gsource = mainloop_add_fd(op->id,
1414 G_PRIORITY_LOW,
1415 op->opaque->stderr_fd, op,
1416 &stderr_callbacks);
1417 services_add_inflight_op(op);
1418 return pcmk_rc_ok;
1419
1420 done:
1421 if (op->synchronous) {
1422 return (op->rc == PCMK_OCF_OK)? pcmk_rc_ok : pcmk_rc_error;
1423 } else {
1424 return services__finalize_async_op(op);
1425 }
1426 }
1427
1428 GList *
1429 services_os_get_single_directory_list(const char *root, gboolean files, gboolean executable)
1430 {
1431 GList *list = NULL;
1432 struct dirent **namelist;
1433 int entries = 0, lpc = 0;
1434 char buffer[PATH_MAX];
1435
1436 entries = scandir(root, &namelist, NULL, alphasort);
1437 if (entries <= 0) {
1438 return list;
1439 }
1440
1441 for (lpc = 0; lpc < entries; lpc++) {
1442 struct stat sb;
1443
1444 if ('.' == namelist[lpc]->d_name[0]) {
1445 free(namelist[lpc]);
1446 continue;
1447 }
1448
1449 snprintf(buffer, sizeof(buffer), "%s/%s", root, namelist[lpc]->d_name);
1450
1451 if (stat(buffer, &sb)) {
1452 continue;
1453 }
1454
1455 if (S_ISDIR(sb.st_mode)) {
1456 if (files) {
1457 free(namelist[lpc]);
1458 continue;
1459 }
1460
1461 } else if (S_ISREG(sb.st_mode)) {
1462 if (files == FALSE) {
1463 free(namelist[lpc]);
1464 continue;
1465
1466 } else if (executable
1467 && (sb.st_mode & S_IXUSR) == 0
1468 && (sb.st_mode & S_IXGRP) == 0 && (sb.st_mode & S_IXOTH) == 0) {
1469 free(namelist[lpc]);
1470 continue;
1471 }
1472 }
1473
1474 list = g_list_append(list, strdup(namelist[lpc]->d_name));
1475
1476 free(namelist[lpc]);
1477 }
1478
1479 free(namelist);
1480 return list;
1481 }
1482
1483 GList *
1484 services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
1485 {
1486 GList *result = NULL;
1487 char *dirs = strdup(root);
1488 char *dir = NULL;
1489
1490 if (pcmk__str_empty(dirs)) {
1491 free(dirs);
1492 return result;
1493 }
1494
1495 for (dir = strtok(dirs, ":"); dir != NULL; dir = strtok(NULL, ":")) {
1496 GList *tmp = services_os_get_single_directory_list(dir, files, executable);
1497
1498 if (tmp) {
1499 result = g_list_concat(result, tmp);
1500 }
1501 }
1502
1503 free(dirs);
1504
1505 return result;
1506 }