27 #include "dbus-spawn.h"
28 #include "dbus-sysdeps-unix.h"
29 #include "dbus-internals.h"
30 #include "dbus-test.h"
31 #include "dbus-protocol.h"
45 #include <systemd/sd-journal.h>
48 #if defined(__APPLE__)
49 # include <crt_externs.h>
50 # define environ (*_NSGetEnviron ())
51 #elif !HAVE_DECL_ENVIRON
52 extern char **environ;
89 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
98 to_read =
sizeof (int) * n_ints_in_buf - bytes;
106 ((
char*)buf) + bytes,
109 if (chunk < 0 && errno == EINTR)
116 "Failed to read from child pipe (%s)",
117 _dbus_strerror (errno));
131 *n_ints_read = (int)(bytes /
sizeof(
int));
144 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
153 to_read =
sizeof (pid_t) - bytes;
161 ((
char*)buf) + bytes,
163 if (chunk < 0 && errno == EINTR)
170 "Failed to read from child pipe (%s)",
171 _dbus_strerror (errno));
266 DBusBabysitterFinishedFunc finished_cb;
277 _dbus_babysitter_new (
void)
285 sitter->refcount = 1;
316 sitter->refcount += 1;
338 sitter->refcount -= 1;
339 if (sitter->refcount == 0)
348 close_socket_to_babysitter (sitter);
350 close_error_pipe_from_child (sitter);
361 ret = waitpid (sitter->
sitter_pid, &status, WNOHANG);
373 ret = waitpid (sitter->
sitter_pid, &status, 0);
375 while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR));
381 _dbus_warn (
"Babysitter process not available to be reaped; should not happen");
383 _dbus_warn (
"Unexpected error %d in waitpid() for babysitter: %s",
384 errno, _dbus_strerror (errno));
388 _dbus_verbose (
"Reaped %ld, waiting for babysitter %ld\n",
391 if (WIFEXITED (sitter->
status))
392 _dbus_verbose (
"Babysitter exited with status %d\n",
393 WEXITSTATUS (sitter->
status));
394 else if (WIFSIGNALED (sitter->
status))
395 _dbus_verbose (
"Babysitter received signal %d\n",
396 WTERMSIG (sitter->
status));
398 _dbus_verbose (
"Babysitter exited abnormally\n");
422 r = read_ints (fd, &what, 1, &got, &error);
447 case CHILD_FORK_FAILED:
448 case CHILD_EXEC_FAILED:
452 r = read_ints (fd, &arg, 1, &got, &error);
471 if (what == CHILD_EXITED)
490 sitter->have_child_status =
TRUE;
492 _dbus_verbose (
"recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
493 WIFEXITED (sitter->
status), WIFSIGNALED (sitter->
status),
494 WEXITSTATUS (sitter->
status), WTERMSIG (sitter->
status));
496 else if (what == CHILD_FORK_FAILED)
500 _dbus_verbose (
"recorded fork errnum %d\n", sitter->
errnum);
502 else if (what == CHILD_EXEC_FAILED)
506 _dbus_verbose (
"recorded exec errnum %d\n", sitter->
errnum);
515 r = read_pid (fd, &pid, &error);
534 _dbus_verbose (
"recorded grandchild pid %d\n", sitter->
grandchild_pid);
538 _dbus_warn (
"Unknown message received from babysitter process");
549 _dbus_verbose (
"Closing babysitter\n");
570 _dbus_verbose (
"Closing child error\n");
598 _dbus_verbose (
"Reading data from babysitter\n");
600 close_socket_to_babysitter (sitter);
604 close_socket_to_babysitter (sitter);
614 _dbus_verbose (
"Reading data from child error\n");
616 close_error_pipe_from_child (sitter);
620 close_error_pipe_from_child (sitter);
633 descriptors_ready =
FALSE;
661 while (ret < 0 && errno == EINTR);
663 if (ret == 0 && block)
669 while (ret < 0 && errno == EINTR);
674 descriptors_ready =
TRUE;
680 handle_error_pipe (sitter, fds[i].revents);
682 handle_babysitter_socket (sitter, fds[i].revents);
687 return descriptors_ready;
694 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter.fd >= 0 || (sitter)->error_pipe_from_child >= 0)
708 babysitter_iteration (sitter,
TRUE);
710 _dbus_verbose (
"Got child PID %ld for killing\n",
730 babysitter_iteration (sitter,
FALSE))
756 if (!sitter->have_child_status ||
757 !(WIFEXITED (sitter->
status)))
760 *status = WEXITSTATUS (sitter->
status);
787 "Failed to execute program %s: %s",
793 "Failed to fork a new process %s: %s",
796 else if (sitter->have_child_status)
798 if (WIFEXITED (sitter->
status))
800 "Process %s exited with status %d",
802 else if (WIFSIGNALED (sitter->
status))
804 "Process %s received signal %d",
808 "Process %s exited abnormally",
814 "Process %s exited, reason unknown",
849 unsigned int condition,
867 handle_error_pipe (sitter, revents);
869 handle_babysitter_socket (sitter, revents);
872 babysitter_iteration (sitter,
FALSE))
881 sitter->finished_cb !=
NULL)
883 sitter->finished_cb (sitter, sitter->finished_data);
884 sitter->finished_cb =
NULL;
907 close_and_invalidate (
int *fd)
931 retval = pipe2 (p, O_CLOEXEC);
932 cloexec_done = retval >= 0;
936 if (retval < 0 && errno == ENOSYS)
942 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
948 "Failed to create pipe for communicating with child process (%s)",
949 _dbus_strerror (errno));
965 do_write (
int fd,
const void *buf,
size_t count)
967 size_t bytes_written;
974 ret = write (fd, ((
const char*)buf) + bytes_written, count - bytes_written);
987 bytes_written += ret;
989 if (bytes_written < count)
993 static void write_err_and_exit (
int fd,
int msg) _DBUS_GNUC_NORETURN;
996 write_err_and_exit (
int fd,
int msg)
1000 do_write (fd, &msg,
sizeof (msg));
1001 do_write (fd, &en,
sizeof (en));
1007 write_pid (
int fd, pid_t pid)
1009 int msg = CHILD_PID;
1011 do_write (fd, &msg,
sizeof (msg));
1012 do_write (fd, &pid,
sizeof (pid));
1015 static void write_status_and_exit (
int fd,
int status) _DBUS_GNUC_NORETURN;
1018 write_status_and_exit (
int fd,
int status)
1020 int msg = CHILD_EXITED;
1022 do_write (fd, &msg,
sizeof (msg));
1023 do_write (fd, &status,
sizeof (status));
1028 static void do_exec (
int child_err_report_fd,
1031 DBusSpawnChildSetupFunc child_setup,
1032 void *user_data) _DBUS_GNUC_NORETURN;
1035 do_exec (
int child_err_report_fd,
1038 DBusSpawnChildSetupFunc child_setup,
1041 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1045 _dbus_verbose_reset ();
1050 (* child_setup) (user_data);
1052 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1053 max_open = sysconf (_SC_OPEN_MAX);
1055 for (i = 3; i < max_open; i++)
1059 if (i == child_err_report_fd)
1062 retval = fcntl (i, F_GETFD);
1064 if (retval != -1 && !(retval & FD_CLOEXEC))
1065 _dbus_warn (
"Fd %d did not have the close-on-exec flag set!", i);
1076 #ifdef HAVE_PDPLINUX
1079 pdpl=pdp_get_current();
1082 _dbus_pdplinux_show_text_label_info2(
"New process (i.e. current) label",pdpl);
1083 _dbus_verbose(
"New process UID=%d\n", getuid());
1087 _dbus_verbose(
"New process name %s\n", argv[0]);
1088 _dbus_verbose(
"parameter 1 for execve (%s)\n", argv[1]);
1092 execve (argv[0], argv, envp);
1095 #if defined HAVE_PDPLINUX && defined DBUS_ENABLE_VERBOSE_MODE
1096 _dbus_verbose(
"Exec failed\n");
1099 write_err_and_exit (child_err_report_fd,
1104 check_babysit_events (pid_t grandchild_pid,
1113 ret = waitpid (grandchild_pid, &status, WNOHANG);
1118 while (ret < 0 && errno == EINTR);
1122 _dbus_verbose (
"no child exited\n");
1129 _dbus_warn (
"unexpected waitpid() failure in check_babysit_events(): %s",
1130 _dbus_strerror (errno));
1133 else if (ret == grandchild_pid)
1136 _dbus_verbose (
"reaped child pid %ld\n", (
long) ret);
1138 write_status_and_exit (parent_pipe, status);
1142 _dbus_warn (
"waitpid() reaped pid %d that we've never heard of",
1149 _dbus_verbose (
"babysitter got POLLIN from parent pipe\n");
1155 _dbus_verbose (
"babysitter got POLLERR or POLLHUP from parent\n");
1160 static int babysit_sigchld_pipe = -1;
1163 babysit_signal_handler (
int signo)
1167 int saved_errno = errno;
1171 if (write (babysit_sigchld_pipe, &b, 1) <= 0)
1175 errno = saved_errno;
1178 static void babysit (pid_t grandchild_pid,
1179 int parent_pipe) _DBUS_GNUC_NORETURN;
1182 babysit (pid_t grandchild_pid,
1185 int sigchld_pipe[2];
1190 _dbus_verbose_reset ();
1197 if (pipe (sigchld_pipe) < 0)
1199 _dbus_warn (
"Not enough file descriptors to create pipe in babysitter process");
1203 babysit_sigchld_pipe = sigchld_pipe[
WRITE_END];
1207 write_pid (parent_pipe, grandchild_pid);
1209 check_babysit_events (grandchild_pid, parent_pipe, 0);
1215 pfds[0].
fd = parent_pipe;
1225 _dbus_warn (
"_dbus_poll() error: %s", strerror (errno));
1229 if (pfds[0].revents != 0)
1231 check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
1236 if (read (sigchld_pipe[
READ_END], &b, 1) == -1)
1241 check_babysit_events (grandchild_pid, parent_pipe, 0);
1274 const char *log_name,
1277 DBusSpawnFlags flags,
1278 DBusSpawnChildSetupFunc child_setup,
1281 #ifdef HAVE_PDPLINUX
1288 int child_err_report_pipe[2] = { -1, -1 };
1289 DBusSocket babysitter_pipe[2] = { DBUS_SOCKET_INIT, DBUS_SOCKET_INIT };
1296 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1299 if (sitter_p !=
NULL)
1304 sitter = _dbus_babysitter_new ();
1315 goto cleanup_and_fail;
1324 goto cleanup_and_fail;
1327 if (!make_pipe (child_err_report_pipe, error))
1328 goto cleanup_and_fail;
1331 goto cleanup_and_fail;
1344 goto cleanup_and_fail;
1356 goto cleanup_and_fail;
1365 goto cleanup_and_fail;
1377 goto cleanup_and_fail;
1380 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1383 if (flags & DBUS_SPAWN_REDIRECT_OUTPUT)
1389 fd_out = sd_journal_stream_fd (sitter->
log_name, LOG_INFO,
FALSE);
1390 fd_err = sd_journal_stream_fd (sitter->
log_name, LOG_WARNING,
FALSE);
1400 "Failed to fork (%s)",
1401 _dbus_strerror (errno));
1402 goto cleanup_and_fail;
1412 signal (SIGPIPE, SIG_DFL);
1415 close_and_invalidate (&child_err_report_pipe[
READ_END]);
1416 close_and_invalidate (&babysitter_pipe[0].fd);
1419 grandchild_pid = fork ();
1421 if (grandchild_pid < 0)
1423 write_err_and_exit (babysitter_pipe[1].fd,
1427 else if (grandchild_pid == 0)
1433 fd = open (
"/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
1438 fd = open (
"/proc/self/oom_score_adj", O_WRONLY);
1444 if (write (fd,
"0",
sizeof (
char)) < 0)
1445 _dbus_warn (
"writing oom_score_adj error: %s", strerror (errno));
1451 signal (SIGPIPE, SIG_IGN);
1453 close_and_invalidate (&babysitter_pipe[1].fd);
1457 dup2 (fd_out, STDOUT_FILENO);
1459 dup2 (fd_err, STDERR_FILENO);
1460 close_and_invalidate (&fd_out);
1461 close_and_invalidate (&fd_err);
1463 do_exec (child_err_report_pipe[
WRITE_END],
1466 child_setup, user_data);
1472 #ifdef HAVE_PDPLINUX
1473 _dbus_verbose(
"We are on babysitter !\n");
1474 if(bus_activation_pdplinux_set_proc_label(user_data,connection,(pid_t)grandchild_pid))
1475 _dbus_verbose(
"Set process label success\n");
1477 _dbus_verbose(
"Set process label failed or skipped\n");
1480 close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
1482 close_and_invalidate (&fd_out);
1483 close_and_invalidate (&fd_err);
1485 babysit (grandchild_pid, babysitter_pipe[1].fd);
1492 close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
1493 close_and_invalidate (&babysitter_pipe[1].fd);
1495 close_and_invalidate (&fd_out);
1496 close_and_invalidate (&fd_err);
1500 babysitter_pipe[0].fd = -1;
1503 child_err_report_pipe[
READ_END] = -1;
1507 if (sitter_p !=
NULL)
1514 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1521 _DBUS_ASSERT_ERROR_IS_SET (error);
1523 close_and_invalidate (&child_err_report_pipe[
READ_END]);
1524 close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
1525 close_and_invalidate (&babysitter_pipe[0].fd);
1526 close_and_invalidate (&babysitter_pipe[1].fd);
1528 close_and_invalidate (&fd_out);
1529 close_and_invalidate (&fd_err);
1540 DBusBabysitterFinishedFunc finished,
1543 sitter->finished_cb = finished;
1544 sitter->finished_data = user_data;
1553 babysitter_iteration (sitter,
TRUE);
1560 #ifdef HAVE_PDPLINUX
1568 _dbus_verbose(
"Entry\n");
1569 _dbus_verbose(
"Try to set label to process from connection\n");
1571 _dbus_verbose(
"actdata=%p, connection=%p, pid=%d\n",
1572 actdata,connection,pid);
1574 pdpl=dbus_connection_pdplinux_get_pdpl(connection);
1575 _dbus_pdplinux_show_text_label_info2(
"Connection",pdpl);
1577 #ifdef PDP_FORCE_SET_LABEL_AT_ACTIVATION_TIME
1578 if (0!=pdp_set_pid(pid,pdpl))
1579 _dbus_verbose(
"pdp_set_pid failed!\n");
1583 _dbus_verbose(
"Set label skipped by configuration\n");
1584 _dbus_verbose(
"Exit\n");
1587 if (pdpl) pdpl_put(pdpl);