1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include <sys/socket.h>
31 #include <sys/prctl.h>
32 #include <linux/sched.h>
33 #include <sys/types.h>
37 #include <sys/mount.h>
39 #include <linux/oom.h>
41 #include <linux/seccomp-bpf.h>
46 #include <security/pam_appl.h>
52 #include "capability.h"
55 #include "sd-messages.h"
57 #include "securebits.h"
58 #include "namespace.h"
60 #include "exit-status.h"
62 #include "utmp-wtmp.h"
64 #include "loopback-setup.h"
65 #include "path-util.h"
66 #include "syscall-list.h"
72 #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
73 #define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
75 /* This assumes there is a 'tty' group */
78 static int shift_fds(int fds[], unsigned n_fds) {
79 int start, restart_from;
84 /* Modifies the fds array! (sorts it) */
94 for (i = start; i < (int) n_fds; i++) {
97 /* Already at right index? */
101 if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0)
104 close_nointr_nofail(fds[i]);
107 /* Hmm, the fd we wanted isn't free? Then
108 * let's remember that and try again from here*/
109 if (nfd != i+3 && restart_from < 0)
113 if (restart_from < 0)
116 start = restart_from;
122 static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
131 /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
133 for (i = 0; i < n_fds; i++) {
135 if ((r = fd_nonblock(fds[i], nonblock)) < 0)
138 /* We unconditionally drop FD_CLOEXEC from the fds,
139 * since after all we want to pass these fds to our
142 if ((r = fd_cloexec(fds[i], false)) < 0)
149 _pure_ static const char *tty_path(const ExecContext *context) {
152 if (context->tty_path)
153 return context->tty_path;
155 return "/dev/console";
158 void exec_context_tty_reset(const ExecContext *context) {
161 if (context->tty_vhangup)
162 terminal_vhangup(tty_path(context));
164 if (context->tty_reset)
165 reset_terminal(tty_path(context));
167 if (context->tty_vt_disallocate && context->tty_path)
168 vt_disallocate(context->tty_path);
171 static bool is_terminal_output(ExecOutput o) {
173 o == EXEC_OUTPUT_TTY ||
174 o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
175 o == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
176 o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE;
179 void exec_context_serialize(const ExecContext *context, Unit *u, FILE *f) {
184 if (context->tmp_dir)
185 unit_serialize_item(u, f, "tmp-dir", context->tmp_dir);
187 if (context->var_tmp_dir)
188 unit_serialize_item(u, f, "var-tmp-dir", context->var_tmp_dir);
191 static int open_null_as(int flags, int nfd) {
196 if ((fd = open("/dev/null", flags|O_NOCTTY)) < 0)
200 r = dup2(fd, nfd) < 0 ? -errno : nfd;
201 close_nointr_nofail(fd);
208 static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd) {
210 union sockaddr_union sa = {
211 .un.sun_family = AF_UNIX,
212 .un.sun_path = "/run/systemd/journal/stdout",
216 assert(output < _EXEC_OUTPUT_MAX);
220 fd = socket(AF_UNIX, SOCK_STREAM, 0);
224 r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
226 close_nointr_nofail(fd);
230 if (shutdown(fd, SHUT_RD) < 0) {
231 close_nointr_nofail(fd);
243 context->syslog_identifier ? context->syslog_identifier : ident,
245 context->syslog_priority,
246 !!context->syslog_level_prefix,
247 output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
248 output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
249 is_terminal_output(output));
252 r = dup2(fd, nfd) < 0 ? -errno : nfd;
253 close_nointr_nofail(fd);
259 static int open_terminal_as(const char *path, mode_t mode, int nfd) {
265 if ((fd = open_terminal(path, mode | O_NOCTTY)) < 0)
269 r = dup2(fd, nfd) < 0 ? -errno : nfd;
270 close_nointr_nofail(fd);
277 static bool is_terminal_input(ExecInput i) {
279 i == EXEC_INPUT_TTY ||
280 i == EXEC_INPUT_TTY_FORCE ||
281 i == EXEC_INPUT_TTY_FAIL;
284 static int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
286 if (is_terminal_input(std_input) && !apply_tty_stdin)
287 return EXEC_INPUT_NULL;
289 if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
290 return EXEC_INPUT_NULL;
295 static int fixup_output(ExecOutput std_output, int socket_fd) {
297 if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
298 return EXEC_OUTPUT_INHERIT;
303 static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
308 i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
312 case EXEC_INPUT_NULL:
313 return open_null_as(O_RDONLY, STDIN_FILENO);
316 case EXEC_INPUT_TTY_FORCE:
317 case EXEC_INPUT_TTY_FAIL: {
320 fd = acquire_terminal(tty_path(context),
321 i == EXEC_INPUT_TTY_FAIL,
322 i == EXEC_INPUT_TTY_FORCE,
328 if (fd != STDIN_FILENO) {
329 r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
330 close_nointr_nofail(fd);
337 case EXEC_INPUT_SOCKET:
338 return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
341 assert_not_reached("Unknown input type");
345 static int setup_output(const ExecContext *context, int fileno, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
353 i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
354 o = fixup_output(context->std_output, socket_fd);
356 if (fileno == STDERR_FILENO) {
358 e = fixup_output(context->std_error, socket_fd);
360 /* This expects the input and output are already set up */
362 /* Don't change the stderr file descriptor if we inherit all
363 * the way and are not on a tty */
364 if (e == EXEC_OUTPUT_INHERIT &&
365 o == EXEC_OUTPUT_INHERIT &&
366 i == EXEC_INPUT_NULL &&
367 !is_terminal_input(context->std_input) &&
371 /* Duplicate from stdout if possible */
372 if (e == o || e == EXEC_OUTPUT_INHERIT)
373 return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
377 } else if (o == EXEC_OUTPUT_INHERIT) {
378 /* If input got downgraded, inherit the original value */
379 if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
380 return open_terminal_as(tty_path(context), O_WRONLY, fileno);
382 /* If the input is connected to anything that's not a /dev/null, inherit that... */
383 if (i != EXEC_INPUT_NULL)
384 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
386 /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
390 /* We need to open /dev/null here anew, to get the right access mode. */
391 return open_null_as(O_WRONLY, fileno);
396 case EXEC_OUTPUT_NULL:
397 return open_null_as(O_WRONLY, fileno);
399 case EXEC_OUTPUT_TTY:
400 if (is_terminal_input(i))
401 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
403 /* We don't reset the terminal if this is just about output */
404 return open_terminal_as(tty_path(context), O_WRONLY, fileno);
406 case EXEC_OUTPUT_SYSLOG:
407 case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
408 case EXEC_OUTPUT_KMSG:
409 case EXEC_OUTPUT_KMSG_AND_CONSOLE:
410 case EXEC_OUTPUT_JOURNAL:
411 case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
412 r = connect_logger_as(context, o, ident, unit_id, fileno);
414 log_struct_unit(LOG_CRIT, unit_id,
415 "MESSAGE=Failed to connect std%s of %s to the journal socket: %s",
416 fileno == STDOUT_FILENO ? "out" : "err",
417 unit_id, strerror(-r),
420 r = open_null_as(O_WRONLY, fileno);
424 case EXEC_OUTPUT_SOCKET:
425 assert(socket_fd >= 0);
426 return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
429 assert_not_reached("Unknown error type");
433 static int chown_terminal(int fd, uid_t uid) {
438 /* This might fail. What matters are the results. */
439 (void) fchown(fd, uid, -1);
440 (void) fchmod(fd, TTY_MODE);
442 if (fstat(fd, &st) < 0)
445 if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
451 static int setup_confirm_stdio(int *_saved_stdin,
452 int *_saved_stdout) {
453 int fd = -1, saved_stdin, saved_stdout = -1, r;
455 assert(_saved_stdin);
456 assert(_saved_stdout);
458 saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
462 saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
463 if (saved_stdout < 0) {
468 fd = acquire_terminal(
473 DEFAULT_CONFIRM_USEC);
479 r = chown_terminal(fd, getuid());
483 if (dup2(fd, STDIN_FILENO) < 0) {
488 if (dup2(fd, STDOUT_FILENO) < 0) {
494 close_nointr_nofail(fd);
496 *_saved_stdin = saved_stdin;
497 *_saved_stdout = saved_stdout;
502 if (saved_stdout >= 0)
503 close_nointr_nofail(saved_stdout);
505 if (saved_stdin >= 0)
506 close_nointr_nofail(saved_stdin);
509 close_nointr_nofail(fd);
514 _printf_(1, 2) static int write_confirm_message(const char *format, ...) {
520 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
524 va_start(ap, format);
525 vdprintf(fd, format, ap);
528 close_nointr_nofail(fd);
533 static int restore_confirm_stdio(int *saved_stdin,
539 assert(saved_stdout);
543 if (*saved_stdin >= 0)
544 if (dup2(*saved_stdin, STDIN_FILENO) < 0)
547 if (*saved_stdout >= 0)
548 if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
551 if (*saved_stdin >= 0)
552 close_nointr_nofail(*saved_stdin);
554 if (*saved_stdout >= 0)
555 close_nointr_nofail(*saved_stdout);
560 static int ask_for_confirmation(char *response, char **argv) {
561 int saved_stdout = -1, saved_stdin = -1, r;
564 r = setup_confirm_stdio(&saved_stdin, &saved_stdout);
568 line = exec_command_line(argv);
572 r = ask(response, "yns", "Execute %s? [Yes, No, Skip] ", line);
575 restore_confirm_stdio(&saved_stdin, &saved_stdout);
580 static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
581 bool keep_groups = false;
586 /* Lookup and set GID and supplementary group list. Here too
587 * we avoid NSS lookups for gid=0. */
589 if (context->group || username) {
591 if (context->group) {
592 const char *g = context->group;
594 if ((r = get_group_creds(&g, &gid)) < 0)
598 /* First step, initialize groups from /etc/groups */
599 if (username && gid != 0) {
600 if (initgroups(username, gid) < 0)
606 /* Second step, set our gids */
607 if (setresgid(gid, gid, gid) < 0)
611 if (context->supplementary_groups) {
616 /* Final step, initialize any manually set supplementary groups */
617 assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
619 if (!(gids = new(gid_t, ngroups_max)))
623 if ((k = getgroups(ngroups_max, gids)) < 0) {
630 STRV_FOREACH(i, context->supplementary_groups) {
633 if (k >= ngroups_max) {
639 r = get_group_creds(&g, gids+k);
648 if (setgroups(k, gids) < 0) {
659 static int enforce_user(const ExecContext *context, uid_t uid) {
663 /* Sets (but doesn't lookup) the uid and make sure we keep the
664 * capabilities while doing so. */
666 if (context->capabilities) {
668 static const cap_value_t bits[] = {
669 CAP_SETUID, /* Necessary so that we can run setresuid() below */
670 CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
673 /* First step: If we need to keep capabilities but
674 * drop privileges we need to make sure we keep our
675 * caps, while we drop privileges. */
677 int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
679 if (prctl(PR_GET_SECUREBITS) != sb)
680 if (prctl(PR_SET_SECUREBITS, sb) < 0)
684 /* Second step: set the capabilities. This will reduce
685 * the capabilities to the minimum we need. */
687 if (!(d = cap_dup(context->capabilities)))
690 if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
691 cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0) {
697 if (cap_set_proc(d) < 0) {
706 /* Third step: actually set the uids */
707 if (setresuid(uid, uid, uid) < 0)
710 /* At this point we should have all necessary capabilities but
711 are otherwise a normal user. However, the caps might got
712 corrupted due to the setresuid() so we need clean them up
713 later. This is done outside of this call. */
720 static int null_conv(
722 const struct pam_message **msg,
723 struct pam_response **resp,
726 /* We don't support conversations */
731 static int setup_pam(
737 int fds[], unsigned n_fds) {
739 static const struct pam_conv conv = {
744 pam_handle_t *handle = NULL;
746 int pam_code = PAM_SUCCESS;
749 bool close_session = false;
750 pid_t pam_pid = 0, parent_pid;
757 /* We set up PAM in the parent process, then fork. The child
758 * will then stay around until killed via PR_GET_PDEATHSIG or
759 * systemd via the cgroup logic. It will then remove the PAM
760 * session again. The parent process will exec() the actual
761 * daemon. We do things this way to ensure that the main PID
762 * of the daemon is the one we initially fork()ed. */
764 if (log_get_max_level() < LOG_PRI(LOG_DEBUG))
767 pam_code = pam_start(name, user, &conv, &handle);
768 if (pam_code != PAM_SUCCESS) {
774 pam_code = pam_set_item(handle, PAM_TTY, tty);
775 if (pam_code != PAM_SUCCESS)
779 pam_code = pam_acct_mgmt(handle, flags);
780 if (pam_code != PAM_SUCCESS)
783 pam_code = pam_open_session(handle, flags);
784 if (pam_code != PAM_SUCCESS)
787 close_session = true;
789 e = pam_getenvlist(handle);
791 pam_code = PAM_BUF_ERR;
795 /* Block SIGTERM, so that we know that it won't get lost in
797 if (sigemptyset(&ss) < 0 ||
798 sigaddset(&ss, SIGTERM) < 0 ||
799 sigprocmask(SIG_BLOCK, &ss, &old_ss) < 0)
802 parent_pid = getpid();
812 /* The child's job is to reset the PAM session on
815 /* This string must fit in 10 chars (i.e. the length
816 * of "/sbin/init"), to look pretty in /bin/ps */
817 rename_process("(sd-pam)");
819 /* Make sure we don't keep open the passed fds in this
820 child. We assume that otherwise only those fds are
821 open here that have been opened by PAM. */
822 close_many(fds, n_fds);
824 /* Drop privileges - we don't need any to pam_close_session
825 * and this will make PR_SET_PDEATHSIG work in most cases.
826 * If this fails, ignore the error - but expect sd-pam threads
827 * to fail to exit normally */
828 if (setresuid(uid, uid, uid) < 0)
829 log_error("Error: Failed to setresuid() in sd-pam: %s", strerror(-r));
831 /* Wait until our parent died. This will only work if
832 * the above setresuid() succeeds, otherwise the kernel
833 * will not allow unprivileged parents kill their privileged
834 * children this way. We rely on the control groups kill logic
835 * to do the rest for us. */
836 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
839 /* Check if our parent process might already have
841 if (getppid() == parent_pid) {
843 if (sigwait(&ss, &sig) < 0) {
850 assert(sig == SIGTERM);
855 /* If our parent died we'll end the session */
856 if (getppid() != parent_pid) {
857 pam_code = pam_close_session(handle, flags);
858 if (pam_code != PAM_SUCCESS)
865 pam_end(handle, pam_code | flags);
869 /* If the child was forked off successfully it will do all the
870 * cleanups, so forget about the handle here. */
873 /* Unblock SIGTERM again in the parent */
874 if (sigprocmask(SIG_SETMASK, &old_ss, NULL) < 0)
877 /* We close the log explicitly here, since the PAM modules
878 * might have opened it, but we don't want this fd around. */
887 if (pam_code != PAM_SUCCESS) {
888 log_error("PAM failed: %s", pam_strerror(handle, pam_code));
889 err = -EPERM; /* PAM errors do not map to errno */
891 log_error("PAM failed: %m");
897 pam_code = pam_close_session(handle, flags);
899 pam_end(handle, pam_code | flags);
907 kill(pam_pid, SIGTERM);
908 kill(pam_pid, SIGCONT);
915 static void rename_process_from_path(const char *path) {
916 char process_name[11];
920 /* This resulting string must fit in 10 chars (i.e. the length
921 * of "/sbin/init") to look pretty in /bin/ps */
923 p = path_get_file_name(path);
925 rename_process("(...)");
931 /* The end of the process name is usually more
932 * interesting, since the first bit might just be
938 process_name[0] = '(';
939 memcpy(process_name+1, p, l);
940 process_name[1+l] = ')';
941 process_name[1+l+1] = 0;
943 rename_process(process_name);
946 static int apply_seccomp(uint32_t *syscall_filter) {
947 static const struct sock_filter header[] = {
948 VALIDATE_ARCHITECTURE,
951 static const struct sock_filter footer[] = {
957 struct sock_filter *f;
958 struct sock_fprog prog = {};
960 assert(syscall_filter);
962 /* First: count the syscalls to check for */
963 for (i = 0, n = 0; i < syscall_max(); i++)
964 if (syscall_filter[i >> 4] & (1 << (i & 31)))
967 /* Second: build the filter program from a header the syscall
968 * matches and the footer */
969 f = alloca(sizeof(struct sock_filter) * (ELEMENTSOF(header) + 2*n + ELEMENTSOF(footer)));
970 memcpy(f, header, sizeof(header));
972 for (i = 0, n = 0; i < syscall_max(); i++)
973 if (syscall_filter[i >> 4] & (1 << (i & 31))) {
974 struct sock_filter item[] = {
975 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, INDEX_TO_SYSCALL(i), 0, 1),
976 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
979 assert_cc(ELEMENTSOF(item) == 2);
981 f[ELEMENTSOF(header) + 2*n] = item[0];
982 f[ELEMENTSOF(header) + 2*n+1] = item[1];
987 memcpy(f + (ELEMENTSOF(header) + 2*n), footer, sizeof(footer));
989 /* Third: install the filter */
990 prog.len = ELEMENTSOF(header) + ELEMENTSOF(footer) + 2*n;
992 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0)
998 static void do_idle_pipe_dance(int idle_pipe[4]) {
1001 if (idle_pipe[1] >= 0)
1002 close_nointr_nofail(idle_pipe[1]);
1003 if (idle_pipe[2] >= 0)
1004 close_nointr_nofail(idle_pipe[2]);
1006 if (idle_pipe[0] >= 0) {
1009 r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
1011 if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
1012 /* Signal systemd that we are bored and want to continue. */
1013 write(idle_pipe[3], "x", 1);
1015 /* Wait for systemd to react to the signal above. */
1016 fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
1019 close_nointr_nofail(idle_pipe[0]);
1023 if (idle_pipe[3] >= 0)
1024 close_nointr_nofail(idle_pipe[3]);
1027 int exec_spawn(ExecCommand *command,
1029 ExecContext *context,
1030 int fds[], unsigned n_fds,
1032 bool apply_permissions,
1034 bool apply_tty_stdin,
1036 CGroupControllerMask cgroup_supported,
1037 const char *cgroup_path,
1038 const char *unit_id,
1042 _cleanup_strv_free_ char **files_env = NULL;
1051 assert(fds || n_fds <= 0);
1053 if (context->std_input == EXEC_INPUT_SOCKET ||
1054 context->std_output == EXEC_OUTPUT_SOCKET ||
1055 context->std_error == EXEC_OUTPUT_SOCKET) {
1067 r = exec_context_load_environment(context, &files_env);
1069 log_struct_unit(LOG_ERR,
1071 "MESSAGE=Failed to load environment files: %s", strerror(-r),
1078 argv = command->argv;
1080 line = exec_command_line(argv);
1084 log_struct_unit(LOG_DEBUG,
1086 "EXECUTABLE=%s", command->path,
1087 "MESSAGE=About to execute: %s", line,
1091 if (context->private_tmp && !context->tmp_dir && !context->var_tmp_dir) {
1092 r = setup_tmpdirs(&context->tmp_dir, &context->var_tmp_dir);
1104 const char *username = NULL, *home = NULL, *shell = NULL;
1105 uid_t uid = (uid_t) -1;
1106 gid_t gid = (gid_t) -1;
1107 _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL,
1108 **final_env = NULL, **final_argv = NULL;
1113 rename_process_from_path(command->path);
1115 /* We reset exactly these signals, since they are the
1116 * only ones we set to SIG_IGN in the main daemon. All
1117 * others we leave untouched because we set them to
1118 * SIG_DFL or a valid handler initially, both of which
1119 * will be demoted to SIG_DFL. */
1120 default_signals(SIGNALS_CRASH_HANDLER,
1121 SIGNALS_IGNORE, -1);
1123 if (context->ignore_sigpipe)
1124 ignore_signals(SIGPIPE, -1);
1126 assert_se(sigemptyset(&ss) == 0);
1127 if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) {
1129 r = EXIT_SIGNAL_MASK;
1134 do_idle_pipe_dance(idle_pipe);
1136 /* Close sockets very early to make sure we don't
1137 * block init reexecution because it cannot bind its
1140 err = close_all_fds(socket_fd >= 0 ? &socket_fd : fds,
1141 socket_fd >= 0 ? 1 : n_fds);
1147 if (!context->same_pgrp)
1154 if (context->tcpwrap_name) {
1156 if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) {
1162 for (i = 0; i < (int) n_fds; i++) {
1163 if (!socket_tcpwrap(fds[i], context->tcpwrap_name)) {
1171 exec_context_tty_reset(context);
1173 if (confirm_spawn) {
1176 err = ask_for_confirmation(&response, argv);
1177 if (err == -ETIMEDOUT)
1178 write_confirm_message("Confirmation question timed out, assuming positive response.\n");
1180 write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-err));
1181 else if (response == 's') {
1182 write_confirm_message("Skipping execution.\n");
1186 } else if (response == 'n') {
1187 write_confirm_message("Failing execution.\n");
1193 /* If a socket is connected to STDIN/STDOUT/STDERR, we
1194 * must sure to drop O_NONBLOCK */
1196 fd_nonblock(socket_fd, false);
1198 err = setup_input(context, socket_fd, apply_tty_stdin);
1204 err = setup_output(context, STDOUT_FILENO, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
1210 err = setup_output(context, STDERR_FILENO, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
1217 err = cg_attach_everywhere(cgroup_supported, cgroup_path, 0);
1224 if (context->oom_score_adjust_set) {
1227 snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
1230 if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
1232 r = EXIT_OOM_ADJUST;
1237 if (context->nice_set)
1238 if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
1244 if (context->cpu_sched_set) {
1245 struct sched_param param = {
1246 .sched_priority = context->cpu_sched_priority,
1249 r = sched_setscheduler(0,
1250 context->cpu_sched_policy |
1251 (context->cpu_sched_reset_on_fork ?
1252 SCHED_RESET_ON_FORK : 0),
1256 r = EXIT_SETSCHEDULER;
1261 if (context->cpuset)
1262 if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
1264 r = EXIT_CPUAFFINITY;
1268 if (context->ioprio_set)
1269 if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
1275 if (context->timer_slack_nsec != (nsec_t) -1)
1276 if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
1278 r = EXIT_TIMERSLACK;
1282 if (context->utmp_id)
1283 utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path);
1285 if (context->user) {
1286 username = context->user;
1287 err = get_user_creds(&username, &uid, &gid, &home, &shell);
1293 if (is_terminal_input(context->std_input)) {
1294 err = chown_terminal(STDIN_FILENO, uid);
1303 if (cgroup_path && context->user && context->pam_name) {
1304 err = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, 0644, uid, gid);
1311 err = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, 0755, uid, gid);
1319 if (apply_permissions) {
1320 err = enforce_groups(context, username, gid);
1327 umask(context->umask);
1330 if (apply_permissions && context->pam_name && username) {
1331 err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
1338 if (context->private_network) {
1339 if (unshare(CLONE_NEWNET) < 0) {
1348 if (strv_length(context->read_write_dirs) > 0 ||
1349 strv_length(context->read_only_dirs) > 0 ||
1350 strv_length(context->inaccessible_dirs) > 0 ||
1351 context->mount_flags != 0 ||
1352 context->private_tmp) {
1353 err = setup_namespace(context->read_write_dirs,
1354 context->read_only_dirs,
1355 context->inaccessible_dirs,
1357 context->var_tmp_dir,
1358 context->private_tmp,
1359 context->mount_flags);
1367 if (context->root_directory)
1368 if (chroot(context->root_directory) < 0) {
1374 if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
1380 _cleanup_free_ char *d = NULL;
1382 if (asprintf(&d, "%s/%s",
1383 context->root_directory ? context->root_directory : "",
1384 context->working_directory ? context->working_directory : "") < 0) {
1397 /* We repeat the fd closing here, to make sure that
1398 * nothing is leaked from the PAM modules */
1399 err = close_all_fds(fds, n_fds);
1401 err = shift_fds(fds, n_fds);
1403 err = flags_fds(fds, n_fds, context->non_blocking);
1409 if (apply_permissions) {
1411 for (i = 0; i < RLIMIT_NLIMITS; i++) {
1412 if (!context->rlimit[i])
1415 if (setrlimit_closest(i, context->rlimit[i]) < 0) {
1422 if (context->capability_bounding_set_drop) {
1423 err = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
1425 r = EXIT_CAPABILITIES;
1430 if (context->user) {
1431 err = enforce_user(context, uid);
1438 /* PR_GET_SECUREBITS is not privileged, while
1439 * PR_SET_SECUREBITS is. So to suppress
1440 * potential EPERMs we'll try not to call
1441 * PR_SET_SECUREBITS unless necessary. */
1442 if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
1443 if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
1445 r = EXIT_SECUREBITS;
1449 if (context->capabilities)
1450 if (cap_set_proc(context->capabilities) < 0) {
1452 r = EXIT_CAPABILITIES;
1456 if (context->no_new_privileges)
1457 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
1459 r = EXIT_NO_NEW_PRIVILEGES;
1463 if (context->syscall_filter) {
1464 err = apply_seccomp(context->syscall_filter);
1472 our_env = new(char*, 8);
1475 asprintf(our_env + n_env++, "LISTEN_PID=%lu", (unsigned long) getpid()) < 0 ||
1476 asprintf(our_env + n_env++, "LISTEN_FDS=%u", n_fds) < 0)) ||
1477 (home && asprintf(our_env + n_env++, "HOME=%s", home) < 0) ||
1479 asprintf(our_env + n_env++, "LOGNAME=%s", username) < 0 ||
1480 asprintf(our_env + n_env++, "USER=%s", username) < 0)) ||
1481 (shell && asprintf(our_env + n_env++, "SHELL=%s", shell) < 0) ||
1482 ((is_terminal_input(context->std_input) ||
1483 context->std_output == EXEC_OUTPUT_TTY ||
1484 context->std_error == EXEC_OUTPUT_TTY) && (
1485 !(our_env[n_env++] = strdup(default_term_for_tty(tty_path(context))))))) {
1492 our_env[n_env++] = NULL;
1495 final_env = strv_env_merge(5,
1498 context->environment,
1508 final_argv = replace_env_argv(argv, final_env);
1515 final_env = strv_env_clean(final_env);
1517 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1518 line = exec_command_line(final_argv);
1521 log_struct_unit(LOG_DEBUG,
1523 "EXECUTABLE=%s", command->path,
1524 "MESSAGE=Executing: %s", line,
1531 execve(command->path, final_argv, final_env);
1538 log_struct(LOG_ERR, MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
1539 "EXECUTABLE=%s", command->path,
1540 "MESSAGE=Failed at step %s spawning %s: %s",
1541 exit_status_to_string(r, EXIT_STATUS_SYSTEMD),
1542 command->path, strerror(-err),
1551 log_struct_unit(LOG_DEBUG,
1553 "MESSAGE=Forked %s as %lu",
1554 command->path, (unsigned long) pid,
1557 /* We add the new process to the cgroup both in the child (so
1558 * that we can be sure that no user code is ever executed
1559 * outside of the cgroup) and in the parent (so that we can be
1560 * sure that when we kill the cgroup the process will be
1563 cg_attach(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, pid);
1565 exec_status_start(&command->exec_status, pid);
1571 void exec_context_init(ExecContext *c) {
1575 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
1576 c->cpu_sched_policy = SCHED_OTHER;
1577 c->syslog_priority = LOG_DAEMON|LOG_INFO;
1578 c->syslog_level_prefix = true;
1579 c->ignore_sigpipe = true;
1580 c->timer_slack_nsec = (nsec_t) -1;
1583 static void *remove_tmpdir_thread(void *p) {
1585 _cleanup_free_ char *dirp = p;
1590 r = rm_rf_dangerous(dirp, false, true, false);
1591 dir = dirname(dirp);
1593 log_warning("Failed to remove content of temporary directory %s: %s",
1598 log_warning("Failed to remove temporary directory %s: %s",
1605 void exec_context_tmp_dirs_done(ExecContext *c) {
1606 char* dirs[] = {c->tmp_dir ? c->tmp_dir : c->var_tmp_dir,
1607 c->tmp_dir ? c->var_tmp_dir : NULL,
1611 for(dirp = dirs; *dirp; dirp++) {
1612 log_debug("Spawning thread to nuke %s", *dirp);
1613 asynchronous_job(remove_tmpdir_thread, *dirp);
1616 c->tmp_dir = c->var_tmp_dir = NULL;
1619 void exec_context_done(ExecContext *c, bool reloading_or_reexecuting) {
1624 strv_free(c->environment);
1625 c->environment = NULL;
1627 strv_free(c->environment_files);
1628 c->environment_files = NULL;
1630 for (l = 0; l < ELEMENTSOF(c->rlimit); l++) {
1632 c->rlimit[l] = NULL;
1635 free(c->working_directory);
1636 c->working_directory = NULL;
1637 free(c->root_directory);
1638 c->root_directory = NULL;
1643 free(c->tcpwrap_name);
1644 c->tcpwrap_name = NULL;
1646 free(c->syslog_identifier);
1647 c->syslog_identifier = NULL;
1655 strv_free(c->supplementary_groups);
1656 c->supplementary_groups = NULL;
1661 if (c->capabilities) {
1662 cap_free(c->capabilities);
1663 c->capabilities = NULL;
1666 strv_free(c->read_only_dirs);
1667 c->read_only_dirs = NULL;
1669 strv_free(c->read_write_dirs);
1670 c->read_write_dirs = NULL;
1672 strv_free(c->inaccessible_dirs);
1673 c->inaccessible_dirs = NULL;
1676 CPU_FREE(c->cpuset);
1681 free(c->syscall_filter);
1682 c->syscall_filter = NULL;
1684 if (!reloading_or_reexecuting)
1685 exec_context_tmp_dirs_done(c);
1688 void exec_command_done(ExecCommand *c) {
1698 void exec_command_done_array(ExecCommand *c, unsigned n) {
1701 for (i = 0; i < n; i++)
1702 exec_command_done(c+i);
1705 void exec_command_free_list(ExecCommand *c) {
1709 LIST_REMOVE(command, c, i);
1710 exec_command_done(i);
1715 void exec_command_free_array(ExecCommand **c, unsigned n) {
1718 for (i = 0; i < n; i++) {
1719 exec_command_free_list(c[i]);
1724 int exec_context_load_environment(const ExecContext *c, char ***l) {
1725 char **i, **r = NULL;
1730 STRV_FOREACH(i, c->environment_files) {
1733 bool ignore = false;
1735 _cleanup_globfree_ glob_t pglob = {};
1745 if (!path_is_absolute(fn)) {
1753 /* Filename supports globbing, take all matching files */
1755 if (glob(fn, 0, NULL, &pglob) != 0) {
1760 return errno ? -errno : -EINVAL;
1762 count = pglob.gl_pathc;
1770 for (n = 0; n < count; n++) {
1771 k = load_env_file(pglob.gl_pathv[n], NULL, &p);
1779 /* Log invalid environment variables with filename */
1781 p = strv_env_clean_log(p, pglob.gl_pathv[n]);
1788 m = strv_env_merge(2, r, p);
1804 static bool tty_may_match_dev_console(const char *tty) {
1805 char *active = NULL, *console;
1808 if (startswith(tty, "/dev/"))
1811 /* trivial identity? */
1812 if (streq(tty, "console"))
1815 console = resolve_dev_console(&active);
1816 /* if we could not resolve, assume it may */
1820 /* "tty0" means the active VC, so it may be the same sometimes */
1821 b = streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty));
1827 bool exec_context_may_touch_console(ExecContext *ec) {
1828 return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate ||
1829 is_terminal_input(ec->std_input) ||
1830 is_terminal_output(ec->std_output) ||
1831 is_terminal_output(ec->std_error)) &&
1832 tty_may_match_dev_console(tty_path(ec));
1835 static void strv_fprintf(FILE *f, char **l) {
1841 fprintf(f, " %s", *g);
1844 void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
1851 prefix = strempty(prefix);
1855 "%sWorkingDirectory: %s\n"
1856 "%sRootDirectory: %s\n"
1857 "%sNonBlocking: %s\n"
1858 "%sPrivateTmp: %s\n"
1859 "%sPrivateNetwork: %s\n"
1860 "%sIgnoreSIGPIPE: %s\n",
1862 prefix, c->working_directory ? c->working_directory : "/",
1863 prefix, c->root_directory ? c->root_directory : "/",
1864 prefix, yes_no(c->non_blocking),
1865 prefix, yes_no(c->private_tmp),
1866 prefix, yes_no(c->private_network),
1867 prefix, yes_no(c->ignore_sigpipe));
1869 STRV_FOREACH(e, c->environment)
1870 fprintf(f, "%sEnvironment: %s\n", prefix, *e);
1872 STRV_FOREACH(e, c->environment_files)
1873 fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
1875 if (c->tcpwrap_name)
1877 "%sTCPWrapName: %s\n",
1878 prefix, c->tcpwrap_name);
1885 if (c->oom_score_adjust_set)
1887 "%sOOMScoreAdjust: %i\n",
1888 prefix, c->oom_score_adjust);
1890 for (i = 0; i < RLIM_NLIMITS; i++)
1892 fprintf(f, "%s%s: %llu\n", prefix, rlimit_to_string(i), (unsigned long long) c->rlimit[i]->rlim_max);
1894 if (c->ioprio_set) {
1898 r = ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
1902 "%sIOSchedulingClass: %s\n"
1903 "%sIOPriority: %i\n",
1904 prefix, strna(class_str),
1905 prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
1909 if (c->cpu_sched_set) {
1913 r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
1917 "%sCPUSchedulingPolicy: %s\n"
1918 "%sCPUSchedulingPriority: %i\n"
1919 "%sCPUSchedulingResetOnFork: %s\n",
1920 prefix, strna(policy_str),
1921 prefix, c->cpu_sched_priority,
1922 prefix, yes_no(c->cpu_sched_reset_on_fork));
1927 fprintf(f, "%sCPUAffinity:", prefix);
1928 for (i = 0; i < c->cpuset_ncpus; i++)
1929 if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
1930 fprintf(f, " %i", i);
1934 if (c->timer_slack_nsec != (nsec_t) -1)
1935 fprintf(f, "%sTimerSlackNSec: %lu\n", prefix, (unsigned long)c->timer_slack_nsec);
1938 "%sStandardInput: %s\n"
1939 "%sStandardOutput: %s\n"
1940 "%sStandardError: %s\n",
1941 prefix, exec_input_to_string(c->std_input),
1942 prefix, exec_output_to_string(c->std_output),
1943 prefix, exec_output_to_string(c->std_error));
1949 "%sTTYVHangup: %s\n"
1950 "%sTTYVTDisallocate: %s\n",
1951 prefix, c->tty_path,
1952 prefix, yes_no(c->tty_reset),
1953 prefix, yes_no(c->tty_vhangup),
1954 prefix, yes_no(c->tty_vt_disallocate));
1956 if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG || c->std_output == EXEC_OUTPUT_JOURNAL ||
1957 c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE ||
1958 c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG || c->std_error == EXEC_OUTPUT_JOURNAL ||
1959 c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE) {
1960 char *fac_str, *lvl_str;
1963 r = log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
1967 r = log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
1972 "%sSyslogFacility: %s\n"
1973 "%sSyslogLevel: %s\n",
1974 prefix, strna(fac_str),
1975 prefix, strna(lvl_str));
1980 if (c->capabilities) {
1982 if ((t = cap_to_text(c->capabilities, NULL))) {
1983 fprintf(f, "%sCapabilities: %s\n",
1990 fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
1992 (c->secure_bits & 1<<SECURE_KEEP_CAPS) ? " keep-caps" : "",
1993 (c->secure_bits & 1<<SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
1994 (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
1995 (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
1996 (c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
1997 (c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
1999 if (c->capability_bounding_set_drop) {
2001 fprintf(f, "%sCapabilityBoundingSet:", prefix);
2003 for (l = 0; l <= cap_last_cap(); l++)
2004 if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l))) {
2007 if ((t = cap_to_name(l))) {
2008 fprintf(f, " %s", t);
2017 fprintf(f, "%sUser: %s\n", prefix, c->user);
2019 fprintf(f, "%sGroup: %s\n", prefix, c->group);
2021 if (strv_length(c->supplementary_groups) > 0) {
2022 fprintf(f, "%sSupplementaryGroups:", prefix);
2023 strv_fprintf(f, c->supplementary_groups);
2028 fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
2030 if (strv_length(c->read_write_dirs) > 0) {
2031 fprintf(f, "%sReadWriteDirs:", prefix);
2032 strv_fprintf(f, c->read_write_dirs);
2036 if (strv_length(c->read_only_dirs) > 0) {
2037 fprintf(f, "%sReadOnlyDirs:", prefix);
2038 strv_fprintf(f, c->read_only_dirs);
2042 if (strv_length(c->inaccessible_dirs) > 0) {
2043 fprintf(f, "%sInaccessibleDirs:", prefix);
2044 strv_fprintf(f, c->inaccessible_dirs);
2050 "%sUtmpIdentifier: %s\n",
2051 prefix, c->utmp_id);
2054 void exec_status_start(ExecStatus *s, pid_t pid) {
2059 dual_timestamp_get(&s->start_timestamp);
2062 void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status) {
2065 if (s->pid && s->pid != pid)
2069 dual_timestamp_get(&s->exit_timestamp);
2075 if (context->utmp_id)
2076 utmp_put_dead_process(context->utmp_id, pid, code, status);
2078 exec_context_tty_reset(context);
2082 void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
2083 char buf[FORMAT_TIMESTAMP_MAX];
2096 prefix, (unsigned long) s->pid);
2098 if (s->start_timestamp.realtime > 0)
2100 "%sStart Timestamp: %s\n",
2101 prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
2103 if (s->exit_timestamp.realtime > 0)
2105 "%sExit Timestamp: %s\n"
2107 "%sExit Status: %i\n",
2108 prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
2109 prefix, sigchld_code_to_string(s->code),
2113 char *exec_command_line(char **argv) {
2121 STRV_FOREACH(a, argv)
2124 if (!(n = new(char, k)))
2128 STRV_FOREACH(a, argv) {
2135 if (strpbrk(*a, WHITESPACE)) {
2146 /* FIXME: this doesn't really handle arguments that have
2147 * spaces and ticks in them */
2152 void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
2154 const char *prefix2;
2163 p2 = strappend(prefix, "\t");
2164 prefix2 = p2 ? p2 : prefix;
2166 cmd = exec_command_line(c->argv);
2169 "%sCommand Line: %s\n",
2170 prefix, cmd ? cmd : strerror(ENOMEM));
2174 exec_status_dump(&c->exec_status, f, prefix2);
2179 void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
2185 LIST_FOREACH(command, c, c)
2186 exec_command_dump(c, f, prefix);
2189 void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
2196 /* It's kind of important, that we keep the order here */
2197 LIST_FIND_TAIL(command, *l, end);
2198 LIST_INSERT_AFTER(command, *l, end, e);
2203 int exec_command_set(ExecCommand *c, const char *path, ...) {
2211 l = strv_new_ap(path, ap);
2217 if (!(p = strdup(path))) {
2231 static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
2232 [EXEC_INPUT_NULL] = "null",
2233 [EXEC_INPUT_TTY] = "tty",
2234 [EXEC_INPUT_TTY_FORCE] = "tty-force",
2235 [EXEC_INPUT_TTY_FAIL] = "tty-fail",
2236 [EXEC_INPUT_SOCKET] = "socket"
2239 DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
2241 static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
2242 [EXEC_OUTPUT_INHERIT] = "inherit",
2243 [EXEC_OUTPUT_NULL] = "null",
2244 [EXEC_OUTPUT_TTY] = "tty",
2245 [EXEC_OUTPUT_SYSLOG] = "syslog",
2246 [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
2247 [EXEC_OUTPUT_KMSG] = "kmsg",
2248 [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
2249 [EXEC_OUTPUT_JOURNAL] = "journal",
2250 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
2251 [EXEC_OUTPUT_SOCKET] = "socket"
2254 DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);