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/personality.h>
30 #include <sys/prctl.h>
31 #include <sys/socket.h>
38 #include <security/pam_appl.h>
42 #include <selinux/selinux.h>
50 #include <sys/apparmor.h>
53 #include "sd-messages.h"
57 #include "apparmor-util.h"
61 #include "bus-endpoint.h"
63 #include "capability.h"
66 #include "errno-list.h"
68 #include "exit-status.h"
71 #include "formats-util.h"
78 #include "namespace.h"
79 #include "parse-util.h"
80 #include "path-util.h"
81 #include "process-util.h"
82 #include "rlimit-util.h"
85 #include "seccomp-util.h"
87 #include "securebits.h"
88 #include "selinux-util.h"
89 #include "signal-util.h"
90 #include "smack-util.h"
91 #include "string-util.h"
93 #include "terminal-util.h"
95 #include "user-util.h"
97 #include "utmp-wtmp.h"
99 #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
100 #define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
102 /* This assumes there is a 'tty' group */
103 #define TTY_MODE 0620
105 #define SNDBUF_SIZE (8*1024*1024)
107 static int shift_fds(int fds
[], unsigned n_fds
) {
108 int start
, restart_from
;
113 /* Modifies the fds array! (sorts it) */
123 for (i
= start
; i
< (int) n_fds
; i
++) {
126 /* Already at right index? */
130 nfd
= fcntl(fds
[i
], F_DUPFD
, i
+ 3);
137 /* Hmm, the fd we wanted isn't free? Then
138 * let's remember that and try again from here */
139 if (nfd
!= i
+3 && restart_from
< 0)
143 if (restart_from
< 0)
146 start
= restart_from
;
152 static int flags_fds(const int fds
[], unsigned n_fds
, bool nonblock
) {
161 /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
163 for (i
= 0; i
< n_fds
; i
++) {
165 r
= fd_nonblock(fds
[i
], nonblock
);
169 /* We unconditionally drop FD_CLOEXEC from the fds,
170 * since after all we want to pass these fds to our
173 r
= fd_cloexec(fds
[i
], false);
181 _pure_
static const char *tty_path(const ExecContext
*context
) {
184 if (context
->tty_path
)
185 return context
->tty_path
;
187 return "/dev/console";
190 static void exec_context_tty_reset(const ExecContext
*context
) {
193 if (context
->tty_vhangup
)
194 terminal_vhangup(tty_path(context
));
196 if (context
->tty_reset
)
197 reset_terminal(tty_path(context
));
199 if (context
->tty_vt_disallocate
&& context
->tty_path
)
200 vt_disallocate(context
->tty_path
);
203 static bool is_terminal_output(ExecOutput o
) {
205 o
== EXEC_OUTPUT_TTY
||
206 o
== EXEC_OUTPUT_SYSLOG_AND_CONSOLE
||
207 o
== EXEC_OUTPUT_KMSG_AND_CONSOLE
||
208 o
== EXEC_OUTPUT_JOURNAL_AND_CONSOLE
;
211 static int open_null_as(int flags
, int nfd
) {
216 fd
= open("/dev/null", flags
|O_NOCTTY
);
221 r
= dup2(fd
, nfd
) < 0 ? -errno
: nfd
;
229 static int connect_journal_socket(int fd
, uid_t uid
, gid_t gid
) {
230 union sockaddr_union sa
= {
231 .un
.sun_family
= AF_UNIX
,
232 .un
.sun_path
= "/run/systemd/journal/stdout",
234 uid_t olduid
= UID_INVALID
;
235 gid_t oldgid
= GID_INVALID
;
238 if (gid
!= GID_INVALID
) {
246 if (uid
!= UID_INVALID
) {
256 r
= connect(fd
, &sa
.sa
, offsetof(struct sockaddr_un
, sun_path
) + strlen(sa
.un
.sun_path
));
260 /* If we fail to restore the uid or gid, things will likely
261 fail later on. This should only happen if an LSM interferes. */
263 if (uid
!= UID_INVALID
)
264 (void) seteuid(olduid
);
267 if (gid
!= GID_INVALID
)
268 (void) setegid(oldgid
);
273 static int connect_logger_as(const ExecContext
*context
, ExecOutput output
, const char *ident
, const char *unit_id
, int nfd
, uid_t uid
, gid_t gid
) {
277 assert(output
< _EXEC_OUTPUT_MAX
);
281 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
285 r
= connect_journal_socket(fd
, uid
, gid
);
289 if (shutdown(fd
, SHUT_RD
) < 0) {
294 fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
304 context
->syslog_identifier
? context
->syslog_identifier
: ident
,
306 context
->syslog_priority
,
307 !!context
->syslog_level_prefix
,
308 output
== EXEC_OUTPUT_SYSLOG
|| output
== EXEC_OUTPUT_SYSLOG_AND_CONSOLE
,
309 output
== EXEC_OUTPUT_KMSG
|| output
== EXEC_OUTPUT_KMSG_AND_CONSOLE
,
310 is_terminal_output(output
));
313 r
= dup2(fd
, nfd
) < 0 ? -errno
: nfd
;
320 static int open_terminal_as(const char *path
, mode_t mode
, int nfd
) {
326 fd
= open_terminal(path
, mode
| O_NOCTTY
);
331 r
= dup2(fd
, nfd
) < 0 ? -errno
: nfd
;
339 static bool is_terminal_input(ExecInput i
) {
341 i
== EXEC_INPUT_TTY
||
342 i
== EXEC_INPUT_TTY_FORCE
||
343 i
== EXEC_INPUT_TTY_FAIL
;
346 static int fixup_input(ExecInput std_input
, int socket_fd
, bool apply_tty_stdin
) {
348 if (is_terminal_input(std_input
) && !apply_tty_stdin
)
349 return EXEC_INPUT_NULL
;
351 if (std_input
== EXEC_INPUT_SOCKET
&& socket_fd
< 0)
352 return EXEC_INPUT_NULL
;
357 static int fixup_output(ExecOutput std_output
, int socket_fd
) {
359 if (std_output
== EXEC_OUTPUT_SOCKET
&& socket_fd
< 0)
360 return EXEC_OUTPUT_INHERIT
;
365 static int setup_input(
366 const ExecContext
*context
,
367 const ExecParameters
*params
,
375 if (params
->stdin_fd
>= 0) {
376 if (dup2(params
->stdin_fd
, STDIN_FILENO
) < 0)
379 /* Try to make this the controlling tty, if it is a tty, and reset it */
380 (void) ioctl(STDIN_FILENO
, TIOCSCTTY
, context
->std_input
== EXEC_INPUT_TTY_FORCE
);
381 (void) reset_terminal_fd(STDIN_FILENO
, true);
386 i
= fixup_input(context
->std_input
, socket_fd
, params
->apply_tty_stdin
);
390 case EXEC_INPUT_NULL
:
391 return open_null_as(O_RDONLY
, STDIN_FILENO
);
394 case EXEC_INPUT_TTY_FORCE
:
395 case EXEC_INPUT_TTY_FAIL
: {
398 fd
= acquire_terminal(tty_path(context
),
399 i
== EXEC_INPUT_TTY_FAIL
,
400 i
== EXEC_INPUT_TTY_FORCE
,
406 if (fd
!= STDIN_FILENO
) {
407 r
= dup2(fd
, STDIN_FILENO
) < 0 ? -errno
: STDIN_FILENO
;
415 case EXEC_INPUT_SOCKET
:
416 return dup2(socket_fd
, STDIN_FILENO
) < 0 ? -errno
: STDIN_FILENO
;
419 assert_not_reached("Unknown input type");
423 static int setup_output(
425 const ExecContext
*context
,
426 const ExecParameters
*params
,
430 uid_t uid
, gid_t gid
) {
441 if (fileno
== STDOUT_FILENO
&& params
->stdout_fd
>= 0) {
443 if (dup2(params
->stdout_fd
, STDOUT_FILENO
) < 0)
446 return STDOUT_FILENO
;
449 if (fileno
== STDERR_FILENO
&& params
->stderr_fd
>= 0) {
450 if (dup2(params
->stderr_fd
, STDERR_FILENO
) < 0)
453 return STDERR_FILENO
;
456 i
= fixup_input(context
->std_input
, socket_fd
, params
->apply_tty_stdin
);
457 o
= fixup_output(context
->std_output
, socket_fd
);
459 if (fileno
== STDERR_FILENO
) {
461 e
= fixup_output(context
->std_error
, socket_fd
);
463 /* This expects the input and output are already set up */
465 /* Don't change the stderr file descriptor if we inherit all
466 * the way and are not on a tty */
467 if (e
== EXEC_OUTPUT_INHERIT
&&
468 o
== EXEC_OUTPUT_INHERIT
&&
469 i
== EXEC_INPUT_NULL
&&
470 !is_terminal_input(context
->std_input
) &&
474 /* Duplicate from stdout if possible */
475 if (e
== o
|| e
== EXEC_OUTPUT_INHERIT
)
476 return dup2(STDOUT_FILENO
, fileno
) < 0 ? -errno
: fileno
;
480 } else if (o
== EXEC_OUTPUT_INHERIT
) {
481 /* If input got downgraded, inherit the original value */
482 if (i
== EXEC_INPUT_NULL
&& is_terminal_input(context
->std_input
))
483 return open_terminal_as(tty_path(context
), O_WRONLY
, fileno
);
485 /* If the input is connected to anything that's not a /dev/null, inherit that... */
486 if (i
!= EXEC_INPUT_NULL
)
487 return dup2(STDIN_FILENO
, fileno
) < 0 ? -errno
: fileno
;
489 /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
493 /* We need to open /dev/null here anew, to get the right access mode. */
494 return open_null_as(O_WRONLY
, fileno
);
499 case EXEC_OUTPUT_NULL
:
500 return open_null_as(O_WRONLY
, fileno
);
502 case EXEC_OUTPUT_TTY
:
503 if (is_terminal_input(i
))
504 return dup2(STDIN_FILENO
, fileno
) < 0 ? -errno
: fileno
;
506 /* We don't reset the terminal if this is just about output */
507 return open_terminal_as(tty_path(context
), O_WRONLY
, fileno
);
509 case EXEC_OUTPUT_SYSLOG
:
510 case EXEC_OUTPUT_SYSLOG_AND_CONSOLE
:
511 case EXEC_OUTPUT_KMSG
:
512 case EXEC_OUTPUT_KMSG_AND_CONSOLE
:
513 case EXEC_OUTPUT_JOURNAL
:
514 case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
:
515 r
= connect_logger_as(context
, o
, ident
, unit
->id
, fileno
, uid
, gid
);
517 log_unit_error_errno(unit
, r
, "Failed to connect %s to the journal socket, ignoring: %m", fileno
== STDOUT_FILENO
? "stdout" : "stderr");
518 r
= open_null_as(O_WRONLY
, fileno
);
522 case EXEC_OUTPUT_SOCKET
:
523 assert(socket_fd
>= 0);
524 return dup2(socket_fd
, fileno
) < 0 ? -errno
: fileno
;
527 assert_not_reached("Unknown error type");
531 static int chown_terminal(int fd
, uid_t uid
) {
536 /* This might fail. What matters are the results. */
537 (void) fchown(fd
, uid
, -1);
538 (void) fchmod(fd
, TTY_MODE
);
540 if (fstat(fd
, &st
) < 0)
543 if (st
.st_uid
!= uid
|| (st
.st_mode
& 0777) != TTY_MODE
)
549 static int setup_confirm_stdio(int *_saved_stdin
, int *_saved_stdout
) {
550 _cleanup_close_
int fd
= -1, saved_stdin
= -1, saved_stdout
= -1;
553 assert(_saved_stdin
);
554 assert(_saved_stdout
);
556 saved_stdin
= fcntl(STDIN_FILENO
, F_DUPFD
, 3);
560 saved_stdout
= fcntl(STDOUT_FILENO
, F_DUPFD
, 3);
561 if (saved_stdout
< 0)
564 fd
= acquire_terminal(
569 DEFAULT_CONFIRM_USEC
);
573 r
= chown_terminal(fd
, getuid());
577 r
= reset_terminal_fd(fd
, true);
581 if (dup2(fd
, STDIN_FILENO
) < 0)
584 if (dup2(fd
, STDOUT_FILENO
) < 0)
591 *_saved_stdin
= saved_stdin
;
592 *_saved_stdout
= saved_stdout
;
594 saved_stdin
= saved_stdout
= -1;
599 _printf_(1, 2) static int write_confirm_message(const char *format
, ...) {
600 _cleanup_close_
int fd
= -1;
605 fd
= open_terminal("/dev/console", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
609 va_start(ap
, format
);
610 vdprintf(fd
, format
, ap
);
616 static int restore_confirm_stdio(int *saved_stdin
, int *saved_stdout
) {
620 assert(saved_stdout
);
624 if (*saved_stdin
>= 0)
625 if (dup2(*saved_stdin
, STDIN_FILENO
) < 0)
628 if (*saved_stdout
>= 0)
629 if (dup2(*saved_stdout
, STDOUT_FILENO
) < 0)
632 *saved_stdin
= safe_close(*saved_stdin
);
633 *saved_stdout
= safe_close(*saved_stdout
);
638 static int ask_for_confirmation(char *response
, char **argv
) {
639 int saved_stdout
= -1, saved_stdin
= -1, r
;
640 _cleanup_free_
char *line
= NULL
;
642 r
= setup_confirm_stdio(&saved_stdin
, &saved_stdout
);
646 line
= exec_command_line(argv
);
650 r
= ask_char(response
, "yns", "Execute %s? [Yes, No, Skip] ", line
);
652 restore_confirm_stdio(&saved_stdin
, &saved_stdout
);
657 static int enforce_groups(const ExecContext
*context
, const char *username
, gid_t gid
) {
658 bool keep_groups
= false;
663 /* Lookup and set GID and supplementary group list. Here too
664 * we avoid NSS lookups for gid=0. */
666 if (context
->group
|| username
) {
667 /* First step, initialize groups from /etc/groups */
668 if (username
&& gid
!= 0) {
669 if (initgroups(username
, gid
) < 0)
675 /* Second step, set our gids */
676 if (setresgid(gid
, gid
, gid
) < 0)
680 if (context
->supplementary_groups
) {
685 /* Final step, initialize any manually set supplementary groups */
686 assert_se((ngroups_max
= (int) sysconf(_SC_NGROUPS_MAX
)) > 0);
688 if (!(gids
= new(gid_t
, ngroups_max
)))
692 k
= getgroups(ngroups_max
, gids
);
700 STRV_FOREACH(i
, context
->supplementary_groups
) {
703 if (k
>= ngroups_max
) {
709 r
= get_group_creds(&g
, gids
+k
);
718 if (setgroups(k
, gids
) < 0) {
729 static int enforce_user(const ExecContext
*context
, uid_t uid
) {
732 /* Sets (but doesn't lookup) the uid and make sure we keep the
733 * capabilities while doing so. */
735 if (context
->capabilities
) {
736 _cleanup_cap_free_ cap_t d
= NULL
;
737 static const cap_value_t bits
[] = {
738 CAP_SETUID
, /* Necessary so that we can run setresuid() below */
739 CAP_SETPCAP
/* Necessary so that we can set PR_SET_SECUREBITS later on */
742 /* First step: If we need to keep capabilities but
743 * drop privileges we need to make sure we keep our
744 * caps, while we drop privileges. */
746 int sb
= context
->secure_bits
| 1<<SECURE_KEEP_CAPS
;
748 if (prctl(PR_GET_SECUREBITS
) != sb
)
749 if (prctl(PR_SET_SECUREBITS
, sb
) < 0)
753 /* Second step: set the capabilities. This will reduce
754 * the capabilities to the minimum we need. */
756 d
= cap_dup(context
->capabilities
);
760 if (cap_set_flag(d
, CAP_EFFECTIVE
, ELEMENTSOF(bits
), bits
, CAP_SET
) < 0 ||
761 cap_set_flag(d
, CAP_PERMITTED
, ELEMENTSOF(bits
), bits
, CAP_SET
) < 0)
764 if (cap_set_proc(d
) < 0)
768 /* Third step: actually set the uids */
769 if (setresuid(uid
, uid
, uid
) < 0)
772 /* At this point we should have all necessary capabilities but
773 are otherwise a normal user. However, the caps might got
774 corrupted due to the setresuid() so we need clean them up
775 later. This is done outside of this call. */
782 static int null_conv(
784 const struct pam_message
**msg
,
785 struct pam_response
**resp
,
788 /* We don't support conversations */
793 static int setup_pam(
799 int fds
[], unsigned n_fds
) {
801 static const struct pam_conv conv
= {
806 _cleanup_(barrier_destroy
) Barrier barrier
= BARRIER_NULL
;
807 pam_handle_t
*handle
= NULL
;
809 int pam_code
= PAM_SUCCESS
;
812 bool close_session
= false;
813 pid_t pam_pid
= 0, parent_pid
;
820 /* We set up PAM in the parent process, then fork. The child
821 * will then stay around until killed via PR_GET_PDEATHSIG or
822 * systemd via the cgroup logic. It will then remove the PAM
823 * session again. The parent process will exec() the actual
824 * daemon. We do things this way to ensure that the main PID
825 * of the daemon is the one we initially fork()ed. */
827 err
= barrier_create(&barrier
);
831 if (log_get_max_level() < LOG_DEBUG
)
834 pam_code
= pam_start(name
, user
, &conv
, &handle
);
835 if (pam_code
!= PAM_SUCCESS
) {
841 pam_code
= pam_set_item(handle
, PAM_TTY
, tty
);
842 if (pam_code
!= PAM_SUCCESS
)
846 pam_code
= pam_acct_mgmt(handle
, flags
);
847 if (pam_code
!= PAM_SUCCESS
)
850 pam_code
= pam_open_session(handle
, flags
);
851 if (pam_code
!= PAM_SUCCESS
)
854 close_session
= true;
856 e
= pam_getenvlist(handle
);
858 pam_code
= PAM_BUF_ERR
;
862 /* Block SIGTERM, so that we know that it won't get lost in
865 assert_se(sigprocmask_many(SIG_BLOCK
, &old_ss
, SIGTERM
, -1) >= 0);
867 parent_pid
= getpid();
877 /* The child's job is to reset the PAM session on
879 barrier_set_role(&barrier
, BARRIER_CHILD
);
881 /* This string must fit in 10 chars (i.e. the length
882 * of "/sbin/init"), to look pretty in /bin/ps */
883 rename_process("(sd-pam)");
885 /* Make sure we don't keep open the passed fds in this
886 child. We assume that otherwise only those fds are
887 open here that have been opened by PAM. */
888 close_many(fds
, n_fds
);
890 /* Drop privileges - we don't need any to pam_close_session
891 * and this will make PR_SET_PDEATHSIG work in most cases.
892 * If this fails, ignore the error - but expect sd-pam threads
893 * to fail to exit normally */
894 if (setresuid(uid
, uid
, uid
) < 0)
895 log_error_errno(r
, "Error: Failed to setresuid() in sd-pam: %m");
897 (void) ignore_signals(SIGPIPE
, -1);
899 /* Wait until our parent died. This will only work if
900 * the above setresuid() succeeds, otherwise the kernel
901 * will not allow unprivileged parents kill their privileged
902 * children this way. We rely on the control groups kill logic
903 * to do the rest for us. */
904 if (prctl(PR_SET_PDEATHSIG
, SIGTERM
) < 0)
907 /* Tell the parent that our setup is done. This is especially
908 * important regarding dropping privileges. Otherwise, unit
909 * setup might race against our setresuid(2) call. */
910 barrier_place(&barrier
);
912 /* Check if our parent process might already have
914 if (getppid() == parent_pid
) {
917 assert_se(sigemptyset(&ss
) >= 0);
918 assert_se(sigaddset(&ss
, SIGTERM
) >= 0);
921 if (sigwait(&ss
, &sig
) < 0) {
928 assert(sig
== SIGTERM
);
933 /* If our parent died we'll end the session */
934 if (getppid() != parent_pid
) {
935 pam_code
= pam_close_session(handle
, flags
);
936 if (pam_code
!= PAM_SUCCESS
)
943 pam_end(handle
, pam_code
| flags
);
947 barrier_set_role(&barrier
, BARRIER_PARENT
);
949 /* If the child was forked off successfully it will do all the
950 * cleanups, so forget about the handle here. */
953 /* Unblock SIGTERM again in the parent */
954 assert_se(sigprocmask(SIG_SETMASK
, &old_ss
, NULL
) >= 0);
956 /* We close the log explicitly here, since the PAM modules
957 * might have opened it, but we don't want this fd around. */
960 /* Synchronously wait for the child to initialize. We don't care for
961 * errors as we cannot recover. However, warn loudly if it happens. */
962 if (!barrier_place_and_sync(&barrier
))
963 log_error("PAM initialization failed");
971 if (pam_code
!= PAM_SUCCESS
) {
972 log_error("PAM failed: %s", pam_strerror(handle
, pam_code
));
973 err
= -EPERM
; /* PAM errors do not map to errno */
975 err
= log_error_errno(err
< 0 ? err
: errno
, "PAM failed: %m");
980 pam_code
= pam_close_session(handle
, flags
);
982 pam_end(handle
, pam_code
| flags
);
990 kill(pam_pid
, SIGTERM
);
991 kill(pam_pid
, SIGCONT
);
998 static void rename_process_from_path(const char *path
) {
999 char process_name
[11];
1003 /* This resulting string must fit in 10 chars (i.e. the length
1004 * of "/sbin/init") to look pretty in /bin/ps */
1008 rename_process("(...)");
1014 /* The end of the process name is usually more
1015 * interesting, since the first bit might just be
1021 process_name
[0] = '(';
1022 memcpy(process_name
+1, p
, l
);
1023 process_name
[1+l
] = ')';
1024 process_name
[1+l
+1] = 0;
1026 rename_process(process_name
);
1031 static int apply_seccomp(const ExecContext
*c
) {
1032 uint32_t negative_action
, action
;
1033 scmp_filter_ctx
*seccomp
;
1040 negative_action
= c
->syscall_errno
== 0 ? SCMP_ACT_KILL
: SCMP_ACT_ERRNO(c
->syscall_errno
);
1042 seccomp
= seccomp_init(c
->syscall_whitelist
? negative_action
: SCMP_ACT_ALLOW
);
1046 if (c
->syscall_archs
) {
1048 SET_FOREACH(id
, c
->syscall_archs
, i
) {
1049 r
= seccomp_arch_add(seccomp
, PTR_TO_UINT32(id
) - 1);
1057 r
= seccomp_add_secondary_archs(seccomp
);
1062 action
= c
->syscall_whitelist
? SCMP_ACT_ALLOW
: negative_action
;
1063 SET_FOREACH(id
, c
->syscall_filter
, i
) {
1064 r
= seccomp_rule_add(seccomp
, action
, PTR_TO_INT(id
) - 1, 0);
1069 r
= seccomp_attr_set(seccomp
, SCMP_FLTATR_CTL_NNP
, 0);
1073 r
= seccomp_load(seccomp
);
1076 seccomp_release(seccomp
);
1080 static int apply_address_families(const ExecContext
*c
) {
1081 scmp_filter_ctx
*seccomp
;
1087 seccomp
= seccomp_init(SCMP_ACT_ALLOW
);
1091 r
= seccomp_add_secondary_archs(seccomp
);
1095 if (c
->address_families_whitelist
) {
1096 int af
, first
= 0, last
= 0;
1099 /* If this is a whitelist, we first block the address
1100 * families that are out of range and then everything
1101 * that is not in the set. First, we find the lowest
1102 * and highest address family in the set. */
1104 SET_FOREACH(afp
, c
->address_families
, i
) {
1105 af
= PTR_TO_INT(afp
);
1107 if (af
<= 0 || af
>= af_max())
1110 if (first
== 0 || af
< first
)
1113 if (last
== 0 || af
> last
)
1117 assert((first
== 0) == (last
== 0));
1121 /* No entries in the valid range, block everything */
1122 r
= seccomp_rule_add(
1124 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1132 /* Block everything below the first entry */
1133 r
= seccomp_rule_add(
1135 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1138 SCMP_A0(SCMP_CMP_LT
, first
));
1142 /* Block everything above the last entry */
1143 r
= seccomp_rule_add(
1145 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1148 SCMP_A0(SCMP_CMP_GT
, last
));
1152 /* Block everything between the first and last
1154 for (af
= 1; af
< af_max(); af
++) {
1156 if (set_contains(c
->address_families
, INT_TO_PTR(af
)))
1159 r
= seccomp_rule_add(
1161 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1164 SCMP_A0(SCMP_CMP_EQ
, af
));
1173 /* If this is a blacklist, then generate one rule for
1174 * each address family that are then combined in OR
1177 SET_FOREACH(af
, c
->address_families
, i
) {
1179 r
= seccomp_rule_add(
1181 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1184 SCMP_A0(SCMP_CMP_EQ
, PTR_TO_INT(af
)));
1190 r
= seccomp_attr_set(seccomp
, SCMP_FLTATR_CTL_NNP
, 0);
1194 r
= seccomp_load(seccomp
);
1197 seccomp_release(seccomp
);
1203 static void do_idle_pipe_dance(int idle_pipe
[4]) {
1207 idle_pipe
[1] = safe_close(idle_pipe
[1]);
1208 idle_pipe
[2] = safe_close(idle_pipe
[2]);
1210 if (idle_pipe
[0] >= 0) {
1213 r
= fd_wait_for_event(idle_pipe
[0], POLLHUP
, IDLE_TIMEOUT_USEC
);
1215 if (idle_pipe
[3] >= 0 && r
== 0 /* timeout */) {
1218 /* Signal systemd that we are bored and want to continue. */
1219 n
= write(idle_pipe
[3], "x", 1);
1221 /* Wait for systemd to react to the signal above. */
1222 fd_wait_for_event(idle_pipe
[0], POLLHUP
, IDLE_TIMEOUT2_USEC
);
1225 idle_pipe
[0] = safe_close(idle_pipe
[0]);
1229 idle_pipe
[3] = safe_close(idle_pipe
[3]);
1232 static int build_environment(
1233 const ExecContext
*c
,
1236 usec_t watchdog_usec
,
1238 const char *username
,
1242 _cleanup_strv_free_
char **our_env
= NULL
;
1249 our_env
= new0(char*, 11);
1254 _cleanup_free_
char *joined
= NULL
;
1256 if (asprintf(&x
, "LISTEN_PID="PID_FMT
, getpid()) < 0)
1258 our_env
[n_env
++] = x
;
1260 if (asprintf(&x
, "LISTEN_FDS=%u", n_fds
) < 0)
1262 our_env
[n_env
++] = x
;
1264 joined
= strv_join(fd_names
, ":");
1268 x
= strjoin("LISTEN_FDNAMES=", joined
, NULL
);
1271 our_env
[n_env
++] = x
;
1274 if (watchdog_usec
> 0) {
1275 if (asprintf(&x
, "WATCHDOG_PID="PID_FMT
, getpid()) < 0)
1277 our_env
[n_env
++] = x
;
1279 if (asprintf(&x
, "WATCHDOG_USEC="USEC_FMT
, watchdog_usec
) < 0)
1281 our_env
[n_env
++] = x
;
1285 x
= strappend("HOME=", home
);
1288 our_env
[n_env
++] = x
;
1292 x
= strappend("LOGNAME=", username
);
1295 our_env
[n_env
++] = x
;
1297 x
= strappend("USER=", username
);
1300 our_env
[n_env
++] = x
;
1304 x
= strappend("SHELL=", shell
);
1307 our_env
[n_env
++] = x
;
1310 if (is_terminal_input(c
->std_input
) ||
1311 c
->std_output
== EXEC_OUTPUT_TTY
||
1312 c
->std_error
== EXEC_OUTPUT_TTY
||
1315 x
= strdup(default_term_for_tty(tty_path(c
)));
1318 our_env
[n_env
++] = x
;
1321 our_env
[n_env
++] = NULL
;
1322 assert(n_env
<= 11);
1330 static bool exec_needs_mount_namespace(
1331 const ExecContext
*context
,
1332 const ExecParameters
*params
,
1333 ExecRuntime
*runtime
) {
1338 if (!strv_isempty(context
->read_write_dirs
) ||
1339 !strv_isempty(context
->read_only_dirs
) ||
1340 !strv_isempty(context
->inaccessible_dirs
))
1343 if (context
->mount_flags
!= 0)
1346 if (context
->private_tmp
&& runtime
&& (runtime
->tmp_dir
|| runtime
->var_tmp_dir
))
1349 if (params
->bus_endpoint_path
)
1352 if (context
->private_devices
||
1353 context
->protect_system
!= PROTECT_SYSTEM_NO
||
1354 context
->protect_home
!= PROTECT_HOME_NO
)
1360 static int close_remaining_fds(
1361 const ExecParameters
*params
,
1362 ExecRuntime
*runtime
,
1364 int *fds
, unsigned n_fds
) {
1366 unsigned n_dont_close
= 0;
1367 int dont_close
[n_fds
+ 7];
1371 if (params
->stdin_fd
>= 0)
1372 dont_close
[n_dont_close
++] = params
->stdin_fd
;
1373 if (params
->stdout_fd
>= 0)
1374 dont_close
[n_dont_close
++] = params
->stdout_fd
;
1375 if (params
->stderr_fd
>= 0)
1376 dont_close
[n_dont_close
++] = params
->stderr_fd
;
1379 dont_close
[n_dont_close
++] = socket_fd
;
1381 memcpy(dont_close
+ n_dont_close
, fds
, sizeof(int) * n_fds
);
1382 n_dont_close
+= n_fds
;
1385 if (params
->bus_endpoint_fd
>= 0)
1386 dont_close
[n_dont_close
++] = params
->bus_endpoint_fd
;
1389 if (runtime
->netns_storage_socket
[0] >= 0)
1390 dont_close
[n_dont_close
++] = runtime
->netns_storage_socket
[0];
1391 if (runtime
->netns_storage_socket
[1] >= 0)
1392 dont_close
[n_dont_close
++] = runtime
->netns_storage_socket
[1];
1395 return close_all_fds(dont_close
, n_dont_close
);
1398 static int exec_child(
1400 ExecCommand
*command
,
1401 const ExecContext
*context
,
1402 const ExecParameters
*params
,
1403 ExecRuntime
*runtime
,
1406 int *fds
, unsigned n_fds
,
1410 _cleanup_strv_free_
char **our_env
= NULL
, **pam_env
= NULL
, **final_env
= NULL
, **final_argv
= NULL
;
1411 _cleanup_free_
char *mac_selinux_context_net
= NULL
;
1412 const char *username
= NULL
, *home
= NULL
, *shell
= NULL
, *wd
;
1413 uid_t uid
= UID_INVALID
;
1414 gid_t gid
= GID_INVALID
;
1416 bool needs_mount_namespace
;
1422 assert(exit_status
);
1424 rename_process_from_path(command
->path
);
1426 /* We reset exactly these signals, since they are the
1427 * only ones we set to SIG_IGN in the main daemon. All
1428 * others we leave untouched because we set them to
1429 * SIG_DFL or a valid handler initially, both of which
1430 * will be demoted to SIG_DFL. */
1431 (void) default_signals(SIGNALS_CRASH_HANDLER
,
1432 SIGNALS_IGNORE
, -1);
1434 if (context
->ignore_sigpipe
)
1435 (void) ignore_signals(SIGPIPE
, -1);
1437 r
= reset_signal_mask();
1439 *exit_status
= EXIT_SIGNAL_MASK
;
1443 if (params
->idle_pipe
)
1444 do_idle_pipe_dance(params
->idle_pipe
);
1446 /* Close sockets very early to make sure we don't
1447 * block init reexecution because it cannot bind its
1452 r
= close_remaining_fds(params
, runtime
, socket_fd
, fds
, n_fds
);
1454 *exit_status
= EXIT_FDS
;
1458 if (!context
->same_pgrp
)
1460 *exit_status
= EXIT_SETSID
;
1464 exec_context_tty_reset(context
);
1466 if (params
->confirm_spawn
) {
1469 r
= ask_for_confirmation(&response
, argv
);
1470 if (r
== -ETIMEDOUT
)
1471 write_confirm_message("Confirmation question timed out, assuming positive response.\n");
1473 write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-r
));
1474 else if (response
== 's') {
1475 write_confirm_message("Skipping execution.\n");
1476 *exit_status
= EXIT_CONFIRM
;
1478 } else if (response
== 'n') {
1479 write_confirm_message("Failing execution.\n");
1485 if (context
->user
) {
1486 username
= context
->user
;
1487 r
= get_user_creds(&username
, &uid
, &gid
, &home
, &shell
);
1489 *exit_status
= EXIT_USER
;
1494 if (context
->group
) {
1495 const char *g
= context
->group
;
1497 r
= get_group_creds(&g
, &gid
);
1499 *exit_status
= EXIT_GROUP
;
1505 /* If a socket is connected to STDIN/STDOUT/STDERR, we
1506 * must sure to drop O_NONBLOCK */
1508 (void) fd_nonblock(socket_fd
, false);
1510 r
= setup_input(context
, params
, socket_fd
);
1512 *exit_status
= EXIT_STDIN
;
1516 r
= setup_output(unit
, context
, params
, STDOUT_FILENO
, socket_fd
, basename(command
->path
), uid
, gid
);
1518 *exit_status
= EXIT_STDOUT
;
1522 r
= setup_output(unit
, context
, params
, STDERR_FILENO
, socket_fd
, basename(command
->path
), uid
, gid
);
1524 *exit_status
= EXIT_STDERR
;
1528 if (params
->cgroup_path
) {
1529 r
= cg_attach_everywhere(params
->cgroup_supported
, params
->cgroup_path
, 0, NULL
, NULL
);
1531 *exit_status
= EXIT_CGROUP
;
1536 if (context
->oom_score_adjust_set
) {
1537 char t
[DECIMAL_STR_MAX(context
->oom_score_adjust
)];
1539 /* When we can't make this change due to EPERM, then
1540 * let's silently skip over it. User namespaces
1541 * prohibit write access to this file, and we
1542 * shouldn't trip up over that. */
1544 sprintf(t
, "%i", context
->oom_score_adjust
);
1545 r
= write_string_file("/proc/self/oom_score_adj", t
, 0);
1546 if (r
== -EPERM
|| r
== -EACCES
) {
1548 log_unit_debug_errno(unit
, r
, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
1551 *exit_status
= EXIT_OOM_ADJUST
;
1556 if (context
->nice_set
)
1557 if (setpriority(PRIO_PROCESS
, 0, context
->nice
) < 0) {
1558 *exit_status
= EXIT_NICE
;
1562 if (context
->cpu_sched_set
) {
1563 struct sched_param param
= {
1564 .sched_priority
= context
->cpu_sched_priority
,
1567 r
= sched_setscheduler(0,
1568 context
->cpu_sched_policy
|
1569 (context
->cpu_sched_reset_on_fork
?
1570 SCHED_RESET_ON_FORK
: 0),
1573 *exit_status
= EXIT_SETSCHEDULER
;
1578 if (context
->cpuset
)
1579 if (sched_setaffinity(0, CPU_ALLOC_SIZE(context
->cpuset_ncpus
), context
->cpuset
) < 0) {
1580 *exit_status
= EXIT_CPUAFFINITY
;
1584 if (context
->ioprio_set
)
1585 if (ioprio_set(IOPRIO_WHO_PROCESS
, 0, context
->ioprio
) < 0) {
1586 *exit_status
= EXIT_IOPRIO
;
1590 if (context
->timer_slack_nsec
!= NSEC_INFINITY
)
1591 if (prctl(PR_SET_TIMERSLACK
, context
->timer_slack_nsec
) < 0) {
1592 *exit_status
= EXIT_TIMERSLACK
;
1596 if (context
->personality
!= PERSONALITY_INVALID
)
1597 if (personality(context
->personality
) < 0) {
1598 *exit_status
= EXIT_PERSONALITY
;
1602 if (context
->utmp_id
)
1603 utmp_put_init_process(context
->utmp_id
, getpid(), getsid(0), context
->tty_path
,
1604 context
->utmp_mode
== EXEC_UTMP_INIT
? INIT_PROCESS
:
1605 context
->utmp_mode
== EXEC_UTMP_LOGIN
? LOGIN_PROCESS
:
1607 username
? "root" : context
->user
);
1609 if (context
->user
&& is_terminal_input(context
->std_input
)) {
1610 r
= chown_terminal(STDIN_FILENO
, uid
);
1612 *exit_status
= EXIT_STDIN
;
1617 if (params
->bus_endpoint_fd
>= 0 && context
->bus_endpoint
) {
1618 uid_t ep_uid
= (uid
== UID_INVALID
) ? 0 : uid
;
1620 r
= bus_kernel_set_endpoint_policy(params
->bus_endpoint_fd
, ep_uid
, context
->bus_endpoint
);
1622 *exit_status
= EXIT_BUS_ENDPOINT
;
1627 /* If delegation is enabled we'll pass ownership of the cgroup
1628 * (but only in systemd's own controller hierarchy!) to the
1629 * user of the new process. */
1630 if (params
->cgroup_path
&& context
->user
&& params
->cgroup_delegate
) {
1631 r
= cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER
, params
->cgroup_path
, 0644, uid
, gid
);
1633 *exit_status
= EXIT_CGROUP
;
1638 r
= cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER
, params
->cgroup_path
, 0755, uid
, gid
);
1640 *exit_status
= EXIT_CGROUP
;
1645 if (!strv_isempty(context
->runtime_directory
) && params
->runtime_prefix
) {
1648 STRV_FOREACH(rt
, context
->runtime_directory
) {
1649 _cleanup_free_
char *p
;
1651 p
= strjoin(params
->runtime_prefix
, "/", *rt
, NULL
);
1653 *exit_status
= EXIT_RUNTIME_DIRECTORY
;
1657 r
= mkdir_p_label(p
, context
->runtime_directory_mode
);
1659 *exit_status
= EXIT_RUNTIME_DIRECTORY
;
1663 r
= chmod_and_chown(p
, context
->runtime_directory_mode
, uid
, gid
);
1665 *exit_status
= EXIT_RUNTIME_DIRECTORY
;
1671 umask(context
->umask
);
1673 if (params
->apply_permissions
) {
1674 r
= enforce_groups(context
, username
, gid
);
1676 *exit_status
= EXIT_GROUP
;
1680 if (context
->smack_process_label
) {
1681 r
= mac_smack_apply_pid(0, context
->smack_process_label
);
1683 *exit_status
= EXIT_SMACK_PROCESS_LABEL
;
1687 #ifdef SMACK_DEFAULT_PROCESS_LABEL
1689 _cleanup_free_
char *exec_label
= NULL
;
1691 r
= mac_smack_read(command
->path
, SMACK_ATTR_EXEC
, &exec_label
);
1692 if (r
< 0 && r
!= -ENODATA
&& r
!= -EOPNOTSUPP
) {
1693 *exit_status
= EXIT_SMACK_PROCESS_LABEL
;
1697 r
= mac_smack_apply_pid(0, exec_label
? : SMACK_DEFAULT_PROCESS_LABEL
);
1699 *exit_status
= EXIT_SMACK_PROCESS_LABEL
;
1706 if (context
->pam_name
&& username
) {
1707 r
= setup_pam(context
->pam_name
, username
, uid
, context
->tty_path
, &pam_env
, fds
, n_fds
);
1709 *exit_status
= EXIT_PAM
;
1716 if (context
->private_network
&& runtime
&& runtime
->netns_storage_socket
[0] >= 0) {
1717 r
= setup_netns(runtime
->netns_storage_socket
);
1719 *exit_status
= EXIT_NETWORK
;
1724 needs_mount_namespace
= exec_needs_mount_namespace(context
, params
, runtime
);
1726 if (needs_mount_namespace
) {
1727 char *tmp
= NULL
, *var
= NULL
;
1729 /* The runtime struct only contains the parent
1730 * of the private /tmp, which is
1731 * non-accessible to world users. Inside of it
1732 * there's a /tmp that is sticky, and that's
1733 * the one we want to use here. */
1735 if (context
->private_tmp
&& runtime
) {
1736 if (runtime
->tmp_dir
)
1737 tmp
= strjoina(runtime
->tmp_dir
, "/tmp");
1738 if (runtime
->var_tmp_dir
)
1739 var
= strjoina(runtime
->var_tmp_dir
, "/tmp");
1742 r
= setup_namespace(
1743 params
->apply_chroot
? context
->root_directory
: NULL
,
1744 context
->read_write_dirs
,
1745 context
->read_only_dirs
,
1746 context
->inaccessible_dirs
,
1749 params
->bus_endpoint_path
,
1750 context
->private_devices
,
1751 context
->protect_home
,
1752 context
->protect_system
,
1753 context
->mount_flags
);
1755 /* If we couldn't set up the namespace this is
1756 * probably due to a missing capability. In this case,
1757 * silently proceeed. */
1758 if (r
== -EPERM
|| r
== -EACCES
) {
1760 log_unit_debug_errno(unit
, r
, "Failed to set up namespace, assuming containerized execution, ignoring: %m");
1763 *exit_status
= EXIT_NAMESPACE
;
1768 if (context
->working_directory_home
)
1770 else if (context
->working_directory
)
1771 wd
= context
->working_directory
;
1775 if (params
->apply_chroot
) {
1776 if (!needs_mount_namespace
&& context
->root_directory
)
1777 if (chroot(context
->root_directory
) < 0) {
1778 *exit_status
= EXIT_CHROOT
;
1782 if (chdir(wd
) < 0 &&
1783 !context
->working_directory_missing_ok
) {
1784 *exit_status
= EXIT_CHDIR
;
1790 d
= strjoina(strempty(context
->root_directory
), "/", strempty(wd
));
1792 !context
->working_directory_missing_ok
) {
1793 *exit_status
= EXIT_CHDIR
;
1799 if (params
->apply_permissions
&& mac_selinux_use() && params
->selinux_context_net
&& socket_fd
>= 0) {
1800 r
= mac_selinux_get_child_mls_label(socket_fd
, command
->path
, context
->selinux_context
, &mac_selinux_context_net
);
1802 *exit_status
= EXIT_SELINUX_CONTEXT
;
1808 /* We repeat the fd closing here, to make sure that
1809 * nothing is leaked from the PAM modules. Note that
1810 * we are more aggressive this time since socket_fd
1811 * and the netns fds we don't need anymore. The custom
1812 * endpoint fd was needed to upload the policy and can
1813 * now be closed as well. */
1814 r
= close_all_fds(fds
, n_fds
);
1816 r
= shift_fds(fds
, n_fds
);
1818 r
= flags_fds(fds
, n_fds
, context
->non_blocking
);
1820 *exit_status
= EXIT_FDS
;
1824 if (params
->apply_permissions
) {
1826 for (i
= 0; i
< _RLIMIT_MAX
; i
++) {
1827 if (!context
->rlimit
[i
])
1830 if (setrlimit_closest(i
, context
->rlimit
[i
]) < 0) {
1831 *exit_status
= EXIT_LIMITS
;
1836 if (context
->capability_bounding_set_drop
) {
1837 r
= capability_bounding_set_drop(context
->capability_bounding_set_drop
, false);
1839 *exit_status
= EXIT_CAPABILITIES
;
1844 if (context
->user
) {
1845 r
= enforce_user(context
, uid
);
1847 *exit_status
= EXIT_USER
;
1852 /* PR_GET_SECUREBITS is not privileged, while
1853 * PR_SET_SECUREBITS is. So to suppress
1854 * potential EPERMs we'll try not to call
1855 * PR_SET_SECUREBITS unless necessary. */
1856 if (prctl(PR_GET_SECUREBITS
) != context
->secure_bits
)
1857 if (prctl(PR_SET_SECUREBITS
, context
->secure_bits
) < 0) {
1858 *exit_status
= EXIT_SECUREBITS
;
1862 if (context
->capabilities
)
1863 if (cap_set_proc(context
->capabilities
) < 0) {
1864 *exit_status
= EXIT_CAPABILITIES
;
1868 if (context
->no_new_privileges
)
1869 if (prctl(PR_SET_NO_NEW_PRIVS
, 1, 0, 0, 0) < 0) {
1870 *exit_status
= EXIT_NO_NEW_PRIVILEGES
;
1875 if (context
->address_families_whitelist
||
1876 !set_isempty(context
->address_families
)) {
1877 r
= apply_address_families(context
);
1879 *exit_status
= EXIT_ADDRESS_FAMILIES
;
1884 if (context
->syscall_whitelist
||
1885 !set_isempty(context
->syscall_filter
) ||
1886 !set_isempty(context
->syscall_archs
)) {
1887 r
= apply_seccomp(context
);
1889 *exit_status
= EXIT_SECCOMP
;
1896 if (mac_selinux_use()) {
1897 char *exec_context
= mac_selinux_context_net
?: context
->selinux_context
;
1900 r
= setexeccon(exec_context
);
1902 *exit_status
= EXIT_SELINUX_CONTEXT
;
1909 #ifdef HAVE_APPARMOR
1910 if (context
->apparmor_profile
&& mac_apparmor_use()) {
1911 r
= aa_change_onexec(context
->apparmor_profile
);
1912 if (r
< 0 && !context
->apparmor_profile_ignore
) {
1913 *exit_status
= EXIT_APPARMOR_PROFILE
;
1920 r
= build_environment(context
, n_fds
, params
->fd_names
, params
->watchdog_usec
, home
, username
, shell
, &our_env
);
1922 *exit_status
= EXIT_MEMORY
;
1926 final_env
= strv_env_merge(5,
1927 params
->environment
,
1929 context
->environment
,
1934 *exit_status
= EXIT_MEMORY
;
1938 final_argv
= replace_env_argv(argv
, final_env
);
1940 *exit_status
= EXIT_MEMORY
;
1944 final_env
= strv_env_clean(final_env
);
1946 if (_unlikely_(log_get_max_level() >= LOG_DEBUG
)) {
1947 _cleanup_free_
char *line
;
1949 line
= exec_command_line(final_argv
);
1952 log_struct(LOG_DEBUG
,
1954 "EXECUTABLE=%s", command
->path
,
1955 LOG_UNIT_MESSAGE(unit
, "Executing: %s", line
),
1961 execve(command
->path
, final_argv
, final_env
);
1962 *exit_status
= EXIT_EXEC
;
1966 int exec_spawn(Unit
*unit
,
1967 ExecCommand
*command
,
1968 const ExecContext
*context
,
1969 const ExecParameters
*params
,
1970 ExecRuntime
*runtime
,
1973 _cleanup_strv_free_
char **files_env
= NULL
;
1974 int *fds
= NULL
; unsigned n_fds
= 0;
1975 _cleanup_free_
char *line
= NULL
;
1985 assert(params
->fds
|| params
->n_fds
<= 0);
1987 if (context
->std_input
== EXEC_INPUT_SOCKET
||
1988 context
->std_output
== EXEC_OUTPUT_SOCKET
||
1989 context
->std_error
== EXEC_OUTPUT_SOCKET
) {
1991 if (params
->n_fds
!= 1) {
1992 log_unit_error(unit
, "Got more than one socket.");
1996 socket_fd
= params
->fds
[0];
2000 n_fds
= params
->n_fds
;
2003 r
= exec_context_load_environment(unit
, context
, &files_env
);
2005 return log_unit_error_errno(unit
, r
, "Failed to load environment files: %m");
2007 argv
= params
->argv
?: command
->argv
;
2008 line
= exec_command_line(argv
);
2012 log_struct(LOG_DEBUG
,
2014 LOG_UNIT_MESSAGE(unit
, "About to execute: %s", line
),
2015 "EXECUTABLE=%s", command
->path
,
2019 return log_unit_error_errno(unit
, r
, "Failed to fork: %m");
2024 r
= exec_child(unit
,
2036 log_struct_errno(LOG_ERR
, r
,
2037 LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED
),
2039 LOG_UNIT_MESSAGE(unit
, "Failed at step %s spawning %s: %m",
2040 exit_status_to_string(exit_status
, EXIT_STATUS_SYSTEMD
),
2042 "EXECUTABLE=%s", command
->path
,
2049 log_unit_debug(unit
, "Forked %s as "PID_FMT
, command
->path
, pid
);
2051 /* We add the new process to the cgroup both in the child (so
2052 * that we can be sure that no user code is ever executed
2053 * outside of the cgroup) and in the parent (so that we can be
2054 * sure that when we kill the cgroup the process will be
2056 if (params
->cgroup_path
)
2057 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER
, params
->cgroup_path
, pid
);
2059 exec_status_start(&command
->exec_status
, pid
);
2065 void exec_context_init(ExecContext
*c
) {
2069 c
->ioprio
= IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE
, 0);
2070 c
->cpu_sched_policy
= SCHED_OTHER
;
2071 c
->syslog_priority
= LOG_DAEMON
|LOG_INFO
;
2072 c
->syslog_level_prefix
= true;
2073 c
->ignore_sigpipe
= true;
2074 c
->timer_slack_nsec
= NSEC_INFINITY
;
2075 c
->personality
= PERSONALITY_INVALID
;
2076 c
->runtime_directory_mode
= 0755;
2079 void exec_context_done(ExecContext
*c
) {
2084 c
->environment
= strv_free(c
->environment
);
2085 c
->environment_files
= strv_free(c
->environment_files
);
2087 for (l
= 0; l
< ELEMENTSOF(c
->rlimit
); l
++)
2088 c
->rlimit
[l
] = mfree(c
->rlimit
[l
]);
2090 c
->working_directory
= mfree(c
->working_directory
);
2091 c
->root_directory
= mfree(c
->root_directory
);
2092 c
->tty_path
= mfree(c
->tty_path
);
2093 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
2094 c
->user
= mfree(c
->user
);
2095 c
->group
= mfree(c
->group
);
2097 c
->supplementary_groups
= strv_free(c
->supplementary_groups
);
2099 c
->pam_name
= mfree(c
->pam_name
);
2101 if (c
->capabilities
) {
2102 cap_free(c
->capabilities
);
2103 c
->capabilities
= NULL
;
2106 c
->read_only_dirs
= strv_free(c
->read_only_dirs
);
2107 c
->read_write_dirs
= strv_free(c
->read_write_dirs
);
2108 c
->inaccessible_dirs
= strv_free(c
->inaccessible_dirs
);
2111 CPU_FREE(c
->cpuset
);
2113 c
->utmp_id
= mfree(c
->utmp_id
);
2114 c
->selinux_context
= mfree(c
->selinux_context
);
2115 c
->apparmor_profile
= mfree(c
->apparmor_profile
);
2117 c
->syscall_filter
= set_free(c
->syscall_filter
);
2118 c
->syscall_archs
= set_free(c
->syscall_archs
);
2119 c
->address_families
= set_free(c
->address_families
);
2121 c
->runtime_directory
= strv_free(c
->runtime_directory
);
2123 bus_endpoint_free(c
->bus_endpoint
);
2124 c
->bus_endpoint
= NULL
;
2127 int exec_context_destroy_runtime_directory(ExecContext
*c
, const char *runtime_prefix
) {
2132 if (!runtime_prefix
)
2135 STRV_FOREACH(i
, c
->runtime_directory
) {
2136 _cleanup_free_
char *p
;
2138 p
= strjoin(runtime_prefix
, "/", *i
, NULL
);
2142 /* We execute this synchronously, since we need to be
2143 * sure this is gone when we start the service
2145 (void) rm_rf(p
, REMOVE_ROOT
);
2151 void exec_command_done(ExecCommand
*c
) {
2154 c
->path
= mfree(c
->path
);
2156 c
->argv
= strv_free(c
->argv
);
2159 void exec_command_done_array(ExecCommand
*c
, unsigned n
) {
2162 for (i
= 0; i
< n
; i
++)
2163 exec_command_done(c
+i
);
2166 ExecCommand
* exec_command_free_list(ExecCommand
*c
) {
2170 LIST_REMOVE(command
, c
, i
);
2171 exec_command_done(i
);
2178 void exec_command_free_array(ExecCommand
**c
, unsigned n
) {
2181 for (i
= 0; i
< n
; i
++)
2182 c
[i
] = exec_command_free_list(c
[i
]);
2185 typedef struct InvalidEnvInfo
{
2190 static void invalid_env(const char *p
, void *userdata
) {
2191 InvalidEnvInfo
*info
= userdata
;
2193 log_unit_error(info
->unit
, "Ignoring invalid environment assignment '%s': %s", p
, info
->path
);
2196 int exec_context_load_environment(Unit
*unit
, const ExecContext
*c
, char ***l
) {
2197 char **i
, **r
= NULL
;
2202 STRV_FOREACH(i
, c
->environment_files
) {
2205 bool ignore
= false;
2207 _cleanup_globfree_ glob_t pglob
= {};
2217 if (!path_is_absolute(fn
)) {
2225 /* Filename supports globbing, take all matching files */
2227 if (glob(fn
, 0, NULL
, &pglob
) != 0) {
2232 return errno
? -errno
: -EINVAL
;
2234 count
= pglob
.gl_pathc
;
2242 for (n
= 0; n
< count
; n
++) {
2243 k
= load_env_file(NULL
, pglob
.gl_pathv
[n
], NULL
, &p
);
2251 /* Log invalid environment variables with filename */
2253 InvalidEnvInfo info
= {
2255 .path
= pglob
.gl_pathv
[n
]
2258 p
= strv_env_clean_with_callback(p
, invalid_env
, &info
);
2266 m
= strv_env_merge(2, r
, p
);
2282 static bool tty_may_match_dev_console(const char *tty
) {
2283 _cleanup_free_
char *active
= NULL
;
2286 if (startswith(tty
, "/dev/"))
2289 /* trivial identity? */
2290 if (streq(tty
, "console"))
2293 console
= resolve_dev_console(&active
);
2294 /* if we could not resolve, assume it may */
2298 /* "tty0" means the active VC, so it may be the same sometimes */
2299 return streq(console
, tty
) || (streq(console
, "tty0") && tty_is_vc(tty
));
2302 bool exec_context_may_touch_console(ExecContext
*ec
) {
2303 return (ec
->tty_reset
|| ec
->tty_vhangup
|| ec
->tty_vt_disallocate
||
2304 is_terminal_input(ec
->std_input
) ||
2305 is_terminal_output(ec
->std_output
) ||
2306 is_terminal_output(ec
->std_error
)) &&
2307 tty_may_match_dev_console(tty_path(ec
));
2310 static void strv_fprintf(FILE *f
, char **l
) {
2316 fprintf(f
, " %s", *g
);
2319 void exec_context_dump(ExecContext
*c
, FILE* f
, const char *prefix
) {
2326 prefix
= strempty(prefix
);
2330 "%sWorkingDirectory: %s\n"
2331 "%sRootDirectory: %s\n"
2332 "%sNonBlocking: %s\n"
2333 "%sPrivateTmp: %s\n"
2334 "%sPrivateNetwork: %s\n"
2335 "%sPrivateDevices: %s\n"
2336 "%sProtectHome: %s\n"
2337 "%sProtectSystem: %s\n"
2338 "%sIgnoreSIGPIPE: %s\n",
2340 prefix
, c
->working_directory
? c
->working_directory
: "/",
2341 prefix
, c
->root_directory
? c
->root_directory
: "/",
2342 prefix
, yes_no(c
->non_blocking
),
2343 prefix
, yes_no(c
->private_tmp
),
2344 prefix
, yes_no(c
->private_network
),
2345 prefix
, yes_no(c
->private_devices
),
2346 prefix
, protect_home_to_string(c
->protect_home
),
2347 prefix
, protect_system_to_string(c
->protect_system
),
2348 prefix
, yes_no(c
->ignore_sigpipe
));
2350 STRV_FOREACH(e
, c
->environment
)
2351 fprintf(f
, "%sEnvironment: %s\n", prefix
, *e
);
2353 STRV_FOREACH(e
, c
->environment_files
)
2354 fprintf(f
, "%sEnvironmentFile: %s\n", prefix
, *e
);
2356 fprintf(f
, "%sRuntimeDirectoryMode: %04o\n", prefix
, c
->runtime_directory_mode
);
2358 STRV_FOREACH(d
, c
->runtime_directory
)
2359 fprintf(f
, "%sRuntimeDirectory: %s\n", prefix
, *d
);
2366 if (c
->oom_score_adjust_set
)
2368 "%sOOMScoreAdjust: %i\n",
2369 prefix
, c
->oom_score_adjust
);
2371 for (i
= 0; i
< RLIM_NLIMITS
; i
++)
2373 fprintf(f
, "%s%s: "RLIM_FMT
"\n",
2374 prefix
, rlimit_to_string(i
), c
->rlimit
[i
]->rlim_max
);
2376 if (c
->ioprio_set
) {
2377 _cleanup_free_
char *class_str
= NULL
;
2379 ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c
->ioprio
), &class_str
);
2381 "%sIOSchedulingClass: %s\n"
2382 "%sIOPriority: %i\n",
2383 prefix
, strna(class_str
),
2384 prefix
, (int) IOPRIO_PRIO_DATA(c
->ioprio
));
2387 if (c
->cpu_sched_set
) {
2388 _cleanup_free_
char *policy_str
= NULL
;
2390 sched_policy_to_string_alloc(c
->cpu_sched_policy
, &policy_str
);
2392 "%sCPUSchedulingPolicy: %s\n"
2393 "%sCPUSchedulingPriority: %i\n"
2394 "%sCPUSchedulingResetOnFork: %s\n",
2395 prefix
, strna(policy_str
),
2396 prefix
, c
->cpu_sched_priority
,
2397 prefix
, yes_no(c
->cpu_sched_reset_on_fork
));
2401 fprintf(f
, "%sCPUAffinity:", prefix
);
2402 for (i
= 0; i
< c
->cpuset_ncpus
; i
++)
2403 if (CPU_ISSET_S(i
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
), c
->cpuset
))
2404 fprintf(f
, " %u", i
);
2408 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
2409 fprintf(f
, "%sTimerSlackNSec: "NSEC_FMT
"\n", prefix
, c
->timer_slack_nsec
);
2412 "%sStandardInput: %s\n"
2413 "%sStandardOutput: %s\n"
2414 "%sStandardError: %s\n",
2415 prefix
, exec_input_to_string(c
->std_input
),
2416 prefix
, exec_output_to_string(c
->std_output
),
2417 prefix
, exec_output_to_string(c
->std_error
));
2423 "%sTTYVHangup: %s\n"
2424 "%sTTYVTDisallocate: %s\n",
2425 prefix
, c
->tty_path
,
2426 prefix
, yes_no(c
->tty_reset
),
2427 prefix
, yes_no(c
->tty_vhangup
),
2428 prefix
, yes_no(c
->tty_vt_disallocate
));
2430 if (c
->std_output
== EXEC_OUTPUT_SYSLOG
||
2431 c
->std_output
== EXEC_OUTPUT_KMSG
||
2432 c
->std_output
== EXEC_OUTPUT_JOURNAL
||
2433 c
->std_output
== EXEC_OUTPUT_SYSLOG_AND_CONSOLE
||
2434 c
->std_output
== EXEC_OUTPUT_KMSG_AND_CONSOLE
||
2435 c
->std_output
== EXEC_OUTPUT_JOURNAL_AND_CONSOLE
||
2436 c
->std_error
== EXEC_OUTPUT_SYSLOG
||
2437 c
->std_error
== EXEC_OUTPUT_KMSG
||
2438 c
->std_error
== EXEC_OUTPUT_JOURNAL
||
2439 c
->std_error
== EXEC_OUTPUT_SYSLOG_AND_CONSOLE
||
2440 c
->std_error
== EXEC_OUTPUT_KMSG_AND_CONSOLE
||
2441 c
->std_error
== EXEC_OUTPUT_JOURNAL_AND_CONSOLE
) {
2443 _cleanup_free_
char *fac_str
= NULL
, *lvl_str
= NULL
;
2445 log_facility_unshifted_to_string_alloc(c
->syslog_priority
>> 3, &fac_str
);
2446 log_level_to_string_alloc(LOG_PRI(c
->syslog_priority
), &lvl_str
);
2449 "%sSyslogFacility: %s\n"
2450 "%sSyslogLevel: %s\n",
2451 prefix
, strna(fac_str
),
2452 prefix
, strna(lvl_str
));
2455 if (c
->capabilities
) {
2456 _cleanup_cap_free_charp_
char *t
;
2458 t
= cap_to_text(c
->capabilities
, NULL
);
2460 fprintf(f
, "%sCapabilities: %s\n", prefix
, t
);
2464 fprintf(f
, "%sSecure Bits:%s%s%s%s%s%s\n",
2466 (c
->secure_bits
& 1<<SECURE_KEEP_CAPS
) ? " keep-caps" : "",
2467 (c
->secure_bits
& 1<<SECURE_KEEP_CAPS_LOCKED
) ? " keep-caps-locked" : "",
2468 (c
->secure_bits
& 1<<SECURE_NO_SETUID_FIXUP
) ? " no-setuid-fixup" : "",
2469 (c
->secure_bits
& 1<<SECURE_NO_SETUID_FIXUP_LOCKED
) ? " no-setuid-fixup-locked" : "",
2470 (c
->secure_bits
& 1<<SECURE_NOROOT
) ? " noroot" : "",
2471 (c
->secure_bits
& 1<<SECURE_NOROOT_LOCKED
) ? "noroot-locked" : "");
2473 if (c
->capability_bounding_set_drop
) {
2475 fprintf(f
, "%sCapabilityBoundingSet:", prefix
);
2477 for (l
= 0; l
<= cap_last_cap(); l
++)
2478 if (!(c
->capability_bounding_set_drop
& ((uint64_t) 1ULL << (uint64_t) l
)))
2479 fprintf(f
, " %s", strna(capability_to_name(l
)));
2485 fprintf(f
, "%sUser: %s\n", prefix
, c
->user
);
2487 fprintf(f
, "%sGroup: %s\n", prefix
, c
->group
);
2489 if (strv_length(c
->supplementary_groups
) > 0) {
2490 fprintf(f
, "%sSupplementaryGroups:", prefix
);
2491 strv_fprintf(f
, c
->supplementary_groups
);
2496 fprintf(f
, "%sPAMName: %s\n", prefix
, c
->pam_name
);
2498 if (strv_length(c
->read_write_dirs
) > 0) {
2499 fprintf(f
, "%sReadWriteDirs:", prefix
);
2500 strv_fprintf(f
, c
->read_write_dirs
);
2504 if (strv_length(c
->read_only_dirs
) > 0) {
2505 fprintf(f
, "%sReadOnlyDirs:", prefix
);
2506 strv_fprintf(f
, c
->read_only_dirs
);
2510 if (strv_length(c
->inaccessible_dirs
) > 0) {
2511 fprintf(f
, "%sInaccessibleDirs:", prefix
);
2512 strv_fprintf(f
, c
->inaccessible_dirs
);
2518 "%sUtmpIdentifier: %s\n",
2519 prefix
, c
->utmp_id
);
2521 if (c
->selinux_context
)
2523 "%sSELinuxContext: %s%s\n",
2524 prefix
, c
->selinux_context_ignore
? "-" : "", c
->selinux_context
);
2526 if (c
->personality
!= PERSONALITY_INVALID
)
2528 "%sPersonality: %s\n",
2529 prefix
, strna(personality_to_string(c
->personality
)));
2531 if (c
->syscall_filter
) {
2539 "%sSystemCallFilter: ",
2542 if (!c
->syscall_whitelist
)
2546 SET_FOREACH(id
, c
->syscall_filter
, j
) {
2547 _cleanup_free_
char *name
= NULL
;
2554 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
2555 fputs(strna(name
), f
);
2562 if (c
->syscall_archs
) {
2569 "%sSystemCallArchitectures:",
2573 SET_FOREACH(id
, c
->syscall_archs
, j
)
2574 fprintf(f
, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1)));
2579 if (c
->syscall_errno
!= 0)
2581 "%sSystemCallErrorNumber: %s\n",
2582 prefix
, strna(errno_to_name(c
->syscall_errno
)));
2584 if (c
->apparmor_profile
)
2586 "%sAppArmorProfile: %s%s\n",
2587 prefix
, c
->apparmor_profile_ignore
? "-" : "", c
->apparmor_profile
);
2590 bool exec_context_maintains_privileges(ExecContext
*c
) {
2593 /* Returns true if the process forked off would run run under
2594 * an unchanged UID or as root. */
2599 if (streq(c
->user
, "root") || streq(c
->user
, "0"))
2605 void exec_status_start(ExecStatus
*s
, pid_t pid
) {
2610 dual_timestamp_get(&s
->start_timestamp
);
2613 void exec_status_exit(ExecStatus
*s
, ExecContext
*context
, pid_t pid
, int code
, int status
) {
2616 if (s
->pid
&& s
->pid
!= pid
)
2620 dual_timestamp_get(&s
->exit_timestamp
);
2626 if (context
->utmp_id
)
2627 utmp_put_dead_process(context
->utmp_id
, pid
, code
, status
);
2629 exec_context_tty_reset(context
);
2633 void exec_status_dump(ExecStatus
*s
, FILE *f
, const char *prefix
) {
2634 char buf
[FORMAT_TIMESTAMP_MAX
];
2642 prefix
= strempty(prefix
);
2645 "%sPID: "PID_FMT
"\n",
2648 if (s
->start_timestamp
.realtime
> 0)
2650 "%sStart Timestamp: %s\n",
2651 prefix
, format_timestamp(buf
, sizeof(buf
), s
->start_timestamp
.realtime
));
2653 if (s
->exit_timestamp
.realtime
> 0)
2655 "%sExit Timestamp: %s\n"
2657 "%sExit Status: %i\n",
2658 prefix
, format_timestamp(buf
, sizeof(buf
), s
->exit_timestamp
.realtime
),
2659 prefix
, sigchld_code_to_string(s
->code
),
2663 char *exec_command_line(char **argv
) {
2671 STRV_FOREACH(a
, argv
)
2674 if (!(n
= new(char, k
)))
2678 STRV_FOREACH(a
, argv
) {
2685 if (strpbrk(*a
, WHITESPACE
)) {
2696 /* FIXME: this doesn't really handle arguments that have
2697 * spaces and ticks in them */
2702 void exec_command_dump(ExecCommand
*c
, FILE *f
, const char *prefix
) {
2703 _cleanup_free_
char *cmd
= NULL
;
2704 const char *prefix2
;
2709 prefix
= strempty(prefix
);
2710 prefix2
= strjoina(prefix
, "\t");
2712 cmd
= exec_command_line(c
->argv
);
2714 "%sCommand Line: %s\n",
2715 prefix
, cmd
? cmd
: strerror(ENOMEM
));
2717 exec_status_dump(&c
->exec_status
, f
, prefix2
);
2720 void exec_command_dump_list(ExecCommand
*c
, FILE *f
, const char *prefix
) {
2723 prefix
= strempty(prefix
);
2725 LIST_FOREACH(command
, c
, c
)
2726 exec_command_dump(c
, f
, prefix
);
2729 void exec_command_append_list(ExecCommand
**l
, ExecCommand
*e
) {
2736 /* It's kind of important, that we keep the order here */
2737 LIST_FIND_TAIL(command
, *l
, end
);
2738 LIST_INSERT_AFTER(command
, *l
, end
, e
);
2743 int exec_command_set(ExecCommand
*c
, const char *path
, ...) {
2751 l
= strv_new_ap(path
, ap
);
2772 int exec_command_append(ExecCommand
*c
, const char *path
, ...) {
2773 _cleanup_strv_free_
char **l
= NULL
;
2781 l
= strv_new_ap(path
, ap
);
2787 r
= strv_extend_strv(&c
->argv
, l
, false);
2795 static int exec_runtime_allocate(ExecRuntime
**rt
) {
2800 *rt
= new0(ExecRuntime
, 1);
2805 (*rt
)->netns_storage_socket
[0] = (*rt
)->netns_storage_socket
[1] = -1;
2810 int exec_runtime_make(ExecRuntime
**rt
, ExecContext
*c
, const char *id
) {
2820 if (!c
->private_network
&& !c
->private_tmp
)
2823 r
= exec_runtime_allocate(rt
);
2827 if (c
->private_network
&& (*rt
)->netns_storage_socket
[0] < 0) {
2828 if (socketpair(AF_UNIX
, SOCK_DGRAM
, 0, (*rt
)->netns_storage_socket
) < 0)
2832 if (c
->private_tmp
&& !(*rt
)->tmp_dir
) {
2833 r
= setup_tmp_dirs(id
, &(*rt
)->tmp_dir
, &(*rt
)->var_tmp_dir
);
2841 ExecRuntime
*exec_runtime_ref(ExecRuntime
*r
) {
2843 assert(r
->n_ref
> 0);
2849 ExecRuntime
*exec_runtime_unref(ExecRuntime
*r
) {
2854 assert(r
->n_ref
> 0);
2861 free(r
->var_tmp_dir
);
2862 safe_close_pair(r
->netns_storage_socket
);
2868 int exec_runtime_serialize(Unit
*u
, ExecRuntime
*rt
, FILE *f
, FDSet
*fds
) {
2877 unit_serialize_item(u
, f
, "tmp-dir", rt
->tmp_dir
);
2879 if (rt
->var_tmp_dir
)
2880 unit_serialize_item(u
, f
, "var-tmp-dir", rt
->var_tmp_dir
);
2882 if (rt
->netns_storage_socket
[0] >= 0) {
2885 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[0]);
2889 unit_serialize_item_format(u
, f
, "netns-socket-0", "%i", copy
);
2892 if (rt
->netns_storage_socket
[1] >= 0) {
2895 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[1]);
2899 unit_serialize_item_format(u
, f
, "netns-socket-1", "%i", copy
);
2905 int exec_runtime_deserialize_item(Unit
*u
, ExecRuntime
**rt
, const char *key
, const char *value
, FDSet
*fds
) {
2912 if (streq(key
, "tmp-dir")) {
2915 r
= exec_runtime_allocate(rt
);
2919 copy
= strdup(value
);
2923 free((*rt
)->tmp_dir
);
2924 (*rt
)->tmp_dir
= copy
;
2926 } else if (streq(key
, "var-tmp-dir")) {
2929 r
= exec_runtime_allocate(rt
);
2933 copy
= strdup(value
);
2937 free((*rt
)->var_tmp_dir
);
2938 (*rt
)->var_tmp_dir
= copy
;
2940 } else if (streq(key
, "netns-socket-0")) {
2943 r
= exec_runtime_allocate(rt
);
2947 if (safe_atoi(value
, &fd
) < 0 || !fdset_contains(fds
, fd
))
2948 log_unit_debug(u
, "Failed to parse netns socket value: %s", value
);
2950 safe_close((*rt
)->netns_storage_socket
[0]);
2951 (*rt
)->netns_storage_socket
[0] = fdset_remove(fds
, fd
);
2953 } else if (streq(key
, "netns-socket-1")) {
2956 r
= exec_runtime_allocate(rt
);
2960 if (safe_atoi(value
, &fd
) < 0 || !fdset_contains(fds
, fd
))
2961 log_unit_debug(u
, "Failed to parse netns socket value: %s", value
);
2963 safe_close((*rt
)->netns_storage_socket
[1]);
2964 (*rt
)->netns_storage_socket
[1] = fdset_remove(fds
, fd
);
2972 static void *remove_tmpdir_thread(void *p
) {
2973 _cleanup_free_
char *path
= p
;
2975 (void) rm_rf(path
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2979 void exec_runtime_destroy(ExecRuntime
*rt
) {
2985 /* If there are multiple users of this, let's leave the stuff around */
2990 log_debug("Spawning thread to nuke %s", rt
->tmp_dir
);
2992 r
= asynchronous_job(remove_tmpdir_thread
, rt
->tmp_dir
);
2994 log_warning_errno(r
, "Failed to nuke %s: %m", rt
->tmp_dir
);
3001 if (rt
->var_tmp_dir
) {
3002 log_debug("Spawning thread to nuke %s", rt
->var_tmp_dir
);
3004 r
= asynchronous_job(remove_tmpdir_thread
, rt
->var_tmp_dir
);
3006 log_warning_errno(r
, "Failed to nuke %s: %m", rt
->var_tmp_dir
);
3007 free(rt
->var_tmp_dir
);
3010 rt
->var_tmp_dir
= NULL
;
3013 safe_close_pair(rt
->netns_storage_socket
);
3016 static const char* const exec_input_table
[_EXEC_INPUT_MAX
] = {
3017 [EXEC_INPUT_NULL
] = "null",
3018 [EXEC_INPUT_TTY
] = "tty",
3019 [EXEC_INPUT_TTY_FORCE
] = "tty-force",
3020 [EXEC_INPUT_TTY_FAIL
] = "tty-fail",
3021 [EXEC_INPUT_SOCKET
] = "socket"
3024 DEFINE_STRING_TABLE_LOOKUP(exec_input
, ExecInput
);
3026 static const char* const exec_output_table
[_EXEC_OUTPUT_MAX
] = {
3027 [EXEC_OUTPUT_INHERIT
] = "inherit",
3028 [EXEC_OUTPUT_NULL
] = "null",
3029 [EXEC_OUTPUT_TTY
] = "tty",
3030 [EXEC_OUTPUT_SYSLOG
] = "syslog",
3031 [EXEC_OUTPUT_SYSLOG_AND_CONSOLE
] = "syslog+console",
3032 [EXEC_OUTPUT_KMSG
] = "kmsg",
3033 [EXEC_OUTPUT_KMSG_AND_CONSOLE
] = "kmsg+console",
3034 [EXEC_OUTPUT_JOURNAL
] = "journal",
3035 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE
] = "journal+console",
3036 [EXEC_OUTPUT_SOCKET
] = "socket"
3039 DEFINE_STRING_TABLE_LOOKUP(exec_output
, ExecOutput
);
3041 static const char* const exec_utmp_mode_table
[_EXEC_UTMP_MODE_MAX
] = {
3042 [EXEC_UTMP_INIT
] = "init",
3043 [EXEC_UTMP_LOGIN
] = "login",
3044 [EXEC_UTMP_USER
] = "user",
3047 DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode
, ExecUtmpMode
);