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"
79 #include "namespace.h"
80 #include "parse-util.h"
81 #include "path-util.h"
82 #include "process-util.h"
83 #include "rlimit-util.h"
86 #include "seccomp-util.h"
88 #include "securebits.h"
89 #include "selinux-util.h"
90 #include "signal-util.h"
91 #include "smack-util.h"
92 #include "string-table.h"
93 #include "string-util.h"
95 #include "terminal-util.h"
97 #include "user-util.h"
99 #include "utmp-wtmp.h"
101 #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
102 #define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
104 /* This assumes there is a 'tty' group */
105 #define TTY_MODE 0620
107 #define SNDBUF_SIZE (8*1024*1024)
109 static int shift_fds(int fds
[], unsigned n_fds
) {
110 int start
, restart_from
;
115 /* Modifies the fds array! (sorts it) */
125 for (i
= start
; i
< (int) n_fds
; i
++) {
128 /* Already at right index? */
132 nfd
= fcntl(fds
[i
], F_DUPFD
, i
+ 3);
139 /* Hmm, the fd we wanted isn't free? Then
140 * let's remember that and try again from here */
141 if (nfd
!= i
+3 && restart_from
< 0)
145 if (restart_from
< 0)
148 start
= restart_from
;
154 static int flags_fds(const int fds
[], unsigned n_fds
, bool nonblock
) {
163 /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
165 for (i
= 0; i
< n_fds
; i
++) {
167 r
= fd_nonblock(fds
[i
], nonblock
);
171 /* We unconditionally drop FD_CLOEXEC from the fds,
172 * since after all we want to pass these fds to our
175 r
= fd_cloexec(fds
[i
], false);
183 _pure_
static const char *tty_path(const ExecContext
*context
) {
186 if (context
->tty_path
)
187 return context
->tty_path
;
189 return "/dev/console";
192 static void exec_context_tty_reset(const ExecContext
*context
) {
195 if (context
->tty_vhangup
)
196 terminal_vhangup(tty_path(context
));
198 if (context
->tty_reset
)
199 reset_terminal(tty_path(context
));
201 if (context
->tty_vt_disallocate
&& context
->tty_path
)
202 vt_disallocate(context
->tty_path
);
205 static bool is_terminal_output(ExecOutput o
) {
207 o
== EXEC_OUTPUT_TTY
||
208 o
== EXEC_OUTPUT_SYSLOG_AND_CONSOLE
||
209 o
== EXEC_OUTPUT_KMSG_AND_CONSOLE
||
210 o
== EXEC_OUTPUT_JOURNAL_AND_CONSOLE
;
213 static int open_null_as(int flags
, int nfd
) {
218 fd
= open("/dev/null", flags
|O_NOCTTY
);
223 r
= dup2(fd
, nfd
) < 0 ? -errno
: nfd
;
231 static int connect_journal_socket(int fd
, uid_t uid
, gid_t gid
) {
232 union sockaddr_union sa
= {
233 .un
.sun_family
= AF_UNIX
,
234 .un
.sun_path
= "/run/systemd/journal/stdout",
236 uid_t olduid
= UID_INVALID
;
237 gid_t oldgid
= GID_INVALID
;
240 if (gid
!= GID_INVALID
) {
248 if (uid
!= UID_INVALID
) {
258 r
= connect(fd
, &sa
.sa
, offsetof(struct sockaddr_un
, sun_path
) + strlen(sa
.un
.sun_path
));
262 /* If we fail to restore the uid or gid, things will likely
263 fail later on. This should only happen if an LSM interferes. */
265 if (uid
!= UID_INVALID
)
266 (void) seteuid(olduid
);
269 if (gid
!= GID_INVALID
)
270 (void) setegid(oldgid
);
275 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
) {
279 assert(output
< _EXEC_OUTPUT_MAX
);
283 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
287 r
= connect_journal_socket(fd
, uid
, gid
);
291 if (shutdown(fd
, SHUT_RD
) < 0) {
296 fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
306 context
->syslog_identifier
? context
->syslog_identifier
: ident
,
308 context
->syslog_priority
,
309 !!context
->syslog_level_prefix
,
310 output
== EXEC_OUTPUT_SYSLOG
|| output
== EXEC_OUTPUT_SYSLOG_AND_CONSOLE
,
311 output
== EXEC_OUTPUT_KMSG
|| output
== EXEC_OUTPUT_KMSG_AND_CONSOLE
,
312 is_terminal_output(output
));
315 r
= dup2(fd
, nfd
) < 0 ? -errno
: nfd
;
322 static int open_terminal_as(const char *path
, mode_t mode
, int nfd
) {
328 fd
= open_terminal(path
, mode
| O_NOCTTY
);
333 r
= dup2(fd
, nfd
) < 0 ? -errno
: nfd
;
341 static bool is_terminal_input(ExecInput i
) {
343 i
== EXEC_INPUT_TTY
||
344 i
== EXEC_INPUT_TTY_FORCE
||
345 i
== EXEC_INPUT_TTY_FAIL
;
348 static int fixup_input(ExecInput std_input
, int socket_fd
, bool apply_tty_stdin
) {
350 if (is_terminal_input(std_input
) && !apply_tty_stdin
)
351 return EXEC_INPUT_NULL
;
353 if (std_input
== EXEC_INPUT_SOCKET
&& socket_fd
< 0)
354 return EXEC_INPUT_NULL
;
359 static int fixup_output(ExecOutput std_output
, int socket_fd
) {
361 if (std_output
== EXEC_OUTPUT_SOCKET
&& socket_fd
< 0)
362 return EXEC_OUTPUT_INHERIT
;
367 static int setup_input(
368 const ExecContext
*context
,
369 const ExecParameters
*params
,
377 if (params
->stdin_fd
>= 0) {
378 if (dup2(params
->stdin_fd
, STDIN_FILENO
) < 0)
381 /* Try to make this the controlling tty, if it is a tty, and reset it */
382 (void) ioctl(STDIN_FILENO
, TIOCSCTTY
, context
->std_input
== EXEC_INPUT_TTY_FORCE
);
383 (void) reset_terminal_fd(STDIN_FILENO
, true);
388 i
= fixup_input(context
->std_input
, socket_fd
, params
->apply_tty_stdin
);
392 case EXEC_INPUT_NULL
:
393 return open_null_as(O_RDONLY
, STDIN_FILENO
);
396 case EXEC_INPUT_TTY_FORCE
:
397 case EXEC_INPUT_TTY_FAIL
: {
400 fd
= acquire_terminal(tty_path(context
),
401 i
== EXEC_INPUT_TTY_FAIL
,
402 i
== EXEC_INPUT_TTY_FORCE
,
408 if (fd
!= STDIN_FILENO
) {
409 r
= dup2(fd
, STDIN_FILENO
) < 0 ? -errno
: STDIN_FILENO
;
417 case EXEC_INPUT_SOCKET
:
418 return dup2(socket_fd
, STDIN_FILENO
) < 0 ? -errno
: STDIN_FILENO
;
421 assert_not_reached("Unknown input type");
425 static int setup_output(
427 const ExecContext
*context
,
428 const ExecParameters
*params
,
432 uid_t uid
, gid_t gid
) {
443 if (fileno
== STDOUT_FILENO
&& params
->stdout_fd
>= 0) {
445 if (dup2(params
->stdout_fd
, STDOUT_FILENO
) < 0)
448 return STDOUT_FILENO
;
451 if (fileno
== STDERR_FILENO
&& params
->stderr_fd
>= 0) {
452 if (dup2(params
->stderr_fd
, STDERR_FILENO
) < 0)
455 return STDERR_FILENO
;
458 i
= fixup_input(context
->std_input
, socket_fd
, params
->apply_tty_stdin
);
459 o
= fixup_output(context
->std_output
, socket_fd
);
461 if (fileno
== STDERR_FILENO
) {
463 e
= fixup_output(context
->std_error
, socket_fd
);
465 /* This expects the input and output are already set up */
467 /* Don't change the stderr file descriptor if we inherit all
468 * the way and are not on a tty */
469 if (e
== EXEC_OUTPUT_INHERIT
&&
470 o
== EXEC_OUTPUT_INHERIT
&&
471 i
== EXEC_INPUT_NULL
&&
472 !is_terminal_input(context
->std_input
) &&
476 /* Duplicate from stdout if possible */
477 if (e
== o
|| e
== EXEC_OUTPUT_INHERIT
)
478 return dup2(STDOUT_FILENO
, fileno
) < 0 ? -errno
: fileno
;
482 } else if (o
== EXEC_OUTPUT_INHERIT
) {
483 /* If input got downgraded, inherit the original value */
484 if (i
== EXEC_INPUT_NULL
&& is_terminal_input(context
->std_input
))
485 return open_terminal_as(tty_path(context
), O_WRONLY
, fileno
);
487 /* If the input is connected to anything that's not a /dev/null, inherit that... */
488 if (i
!= EXEC_INPUT_NULL
)
489 return dup2(STDIN_FILENO
, fileno
) < 0 ? -errno
: fileno
;
491 /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
495 /* We need to open /dev/null here anew, to get the right access mode. */
496 return open_null_as(O_WRONLY
, fileno
);
501 case EXEC_OUTPUT_NULL
:
502 return open_null_as(O_WRONLY
, fileno
);
504 case EXEC_OUTPUT_TTY
:
505 if (is_terminal_input(i
))
506 return dup2(STDIN_FILENO
, fileno
) < 0 ? -errno
: fileno
;
508 /* We don't reset the terminal if this is just about output */
509 return open_terminal_as(tty_path(context
), O_WRONLY
, fileno
);
511 case EXEC_OUTPUT_SYSLOG
:
512 case EXEC_OUTPUT_SYSLOG_AND_CONSOLE
:
513 case EXEC_OUTPUT_KMSG
:
514 case EXEC_OUTPUT_KMSG_AND_CONSOLE
:
515 case EXEC_OUTPUT_JOURNAL
:
516 case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
:
517 r
= connect_logger_as(context
, o
, ident
, unit
->id
, fileno
, uid
, gid
);
519 log_unit_error_errno(unit
, r
, "Failed to connect %s to the journal socket, ignoring: %m", fileno
== STDOUT_FILENO
? "stdout" : "stderr");
520 r
= open_null_as(O_WRONLY
, fileno
);
524 case EXEC_OUTPUT_SOCKET
:
525 assert(socket_fd
>= 0);
526 return dup2(socket_fd
, fileno
) < 0 ? -errno
: fileno
;
529 assert_not_reached("Unknown error type");
533 static int chown_terminal(int fd
, uid_t uid
) {
538 /* This might fail. What matters are the results. */
539 (void) fchown(fd
, uid
, -1);
540 (void) fchmod(fd
, TTY_MODE
);
542 if (fstat(fd
, &st
) < 0)
545 if (st
.st_uid
!= uid
|| (st
.st_mode
& 0777) != TTY_MODE
)
551 static int setup_confirm_stdio(int *_saved_stdin
, int *_saved_stdout
) {
552 _cleanup_close_
int fd
= -1, saved_stdin
= -1, saved_stdout
= -1;
555 assert(_saved_stdin
);
556 assert(_saved_stdout
);
558 saved_stdin
= fcntl(STDIN_FILENO
, F_DUPFD
, 3);
562 saved_stdout
= fcntl(STDOUT_FILENO
, F_DUPFD
, 3);
563 if (saved_stdout
< 0)
566 fd
= acquire_terminal(
571 DEFAULT_CONFIRM_USEC
);
575 r
= chown_terminal(fd
, getuid());
579 r
= reset_terminal_fd(fd
, true);
583 if (dup2(fd
, STDIN_FILENO
) < 0)
586 if (dup2(fd
, STDOUT_FILENO
) < 0)
593 *_saved_stdin
= saved_stdin
;
594 *_saved_stdout
= saved_stdout
;
596 saved_stdin
= saved_stdout
= -1;
601 _printf_(1, 2) static int write_confirm_message(const char *format
, ...) {
602 _cleanup_close_
int fd
= -1;
607 fd
= open_terminal("/dev/console", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
611 va_start(ap
, format
);
612 vdprintf(fd
, format
, ap
);
618 static int restore_confirm_stdio(int *saved_stdin
, int *saved_stdout
) {
622 assert(saved_stdout
);
626 if (*saved_stdin
>= 0)
627 if (dup2(*saved_stdin
, STDIN_FILENO
) < 0)
630 if (*saved_stdout
>= 0)
631 if (dup2(*saved_stdout
, STDOUT_FILENO
) < 0)
634 *saved_stdin
= safe_close(*saved_stdin
);
635 *saved_stdout
= safe_close(*saved_stdout
);
640 static int ask_for_confirmation(char *response
, char **argv
) {
641 int saved_stdout
= -1, saved_stdin
= -1, r
;
642 _cleanup_free_
char *line
= NULL
;
644 r
= setup_confirm_stdio(&saved_stdin
, &saved_stdout
);
648 line
= exec_command_line(argv
);
652 r
= ask_char(response
, "yns", "Execute %s? [Yes, No, Skip] ", line
);
654 restore_confirm_stdio(&saved_stdin
, &saved_stdout
);
659 static int enforce_groups(const ExecContext
*context
, const char *username
, gid_t gid
) {
660 bool keep_groups
= false;
665 /* Lookup and set GID and supplementary group list. Here too
666 * we avoid NSS lookups for gid=0. */
668 if (context
->group
|| username
) {
669 /* First step, initialize groups from /etc/groups */
670 if (username
&& gid
!= 0) {
671 if (initgroups(username
, gid
) < 0)
677 /* Second step, set our gids */
678 if (setresgid(gid
, gid
, gid
) < 0)
682 if (context
->supplementary_groups
) {
687 /* Final step, initialize any manually set supplementary groups */
688 assert_se((ngroups_max
= (int) sysconf(_SC_NGROUPS_MAX
)) > 0);
690 if (!(gids
= new(gid_t
, ngroups_max
)))
694 k
= getgroups(ngroups_max
, gids
);
702 STRV_FOREACH(i
, context
->supplementary_groups
) {
705 if (k
>= ngroups_max
) {
711 r
= get_group_creds(&g
, gids
+k
);
720 if (setgroups(k
, gids
) < 0) {
731 static int enforce_user(const ExecContext
*context
, uid_t uid
) {
734 /* Sets (but doesn't lookup) the uid and make sure we keep the
735 * capabilities while doing so. */
737 if (context
->capabilities
) {
738 _cleanup_cap_free_ cap_t d
= NULL
;
739 static const cap_value_t bits
[] = {
740 CAP_SETUID
, /* Necessary so that we can run setresuid() below */
741 CAP_SETPCAP
/* Necessary so that we can set PR_SET_SECUREBITS later on */
744 /* First step: If we need to keep capabilities but
745 * drop privileges we need to make sure we keep our
746 * caps, while we drop privileges. */
748 int sb
= context
->secure_bits
| 1<<SECURE_KEEP_CAPS
;
750 if (prctl(PR_GET_SECUREBITS
) != sb
)
751 if (prctl(PR_SET_SECUREBITS
, sb
) < 0)
755 /* Second step: set the capabilities. This will reduce
756 * the capabilities to the minimum we need. */
758 d
= cap_dup(context
->capabilities
);
762 if (cap_set_flag(d
, CAP_EFFECTIVE
, ELEMENTSOF(bits
), bits
, CAP_SET
) < 0 ||
763 cap_set_flag(d
, CAP_PERMITTED
, ELEMENTSOF(bits
), bits
, CAP_SET
) < 0)
766 if (cap_set_proc(d
) < 0)
770 /* Third step: actually set the uids */
771 if (setresuid(uid
, uid
, uid
) < 0)
774 /* At this point we should have all necessary capabilities but
775 are otherwise a normal user. However, the caps might got
776 corrupted due to the setresuid() so we need clean them up
777 later. This is done outside of this call. */
784 static int null_conv(
786 const struct pam_message
**msg
,
787 struct pam_response
**resp
,
790 /* We don't support conversations */
795 static int setup_pam(
801 int fds
[], unsigned n_fds
) {
803 static const struct pam_conv conv
= {
808 _cleanup_(barrier_destroy
) Barrier barrier
= BARRIER_NULL
;
809 pam_handle_t
*handle
= NULL
;
811 int pam_code
= PAM_SUCCESS
;
814 bool close_session
= false;
815 pid_t pam_pid
= 0, parent_pid
;
822 /* We set up PAM in the parent process, then fork. The child
823 * will then stay around until killed via PR_GET_PDEATHSIG or
824 * systemd via the cgroup logic. It will then remove the PAM
825 * session again. The parent process will exec() the actual
826 * daemon. We do things this way to ensure that the main PID
827 * of the daemon is the one we initially fork()ed. */
829 err
= barrier_create(&barrier
);
833 if (log_get_max_level() < LOG_DEBUG
)
836 pam_code
= pam_start(name
, user
, &conv
, &handle
);
837 if (pam_code
!= PAM_SUCCESS
) {
843 pam_code
= pam_set_item(handle
, PAM_TTY
, tty
);
844 if (pam_code
!= PAM_SUCCESS
)
848 pam_code
= pam_acct_mgmt(handle
, flags
);
849 if (pam_code
!= PAM_SUCCESS
)
852 pam_code
= pam_open_session(handle
, flags
);
853 if (pam_code
!= PAM_SUCCESS
)
856 close_session
= true;
858 e
= pam_getenvlist(handle
);
860 pam_code
= PAM_BUF_ERR
;
864 /* Block SIGTERM, so that we know that it won't get lost in
867 assert_se(sigprocmask_many(SIG_BLOCK
, &old_ss
, SIGTERM
, -1) >= 0);
869 parent_pid
= getpid();
879 /* The child's job is to reset the PAM session on
881 barrier_set_role(&barrier
, BARRIER_CHILD
);
883 /* This string must fit in 10 chars (i.e. the length
884 * of "/sbin/init"), to look pretty in /bin/ps */
885 rename_process("(sd-pam)");
887 /* Make sure we don't keep open the passed fds in this
888 child. We assume that otherwise only those fds are
889 open here that have been opened by PAM. */
890 close_many(fds
, n_fds
);
892 /* Drop privileges - we don't need any to pam_close_session
893 * and this will make PR_SET_PDEATHSIG work in most cases.
894 * If this fails, ignore the error - but expect sd-pam threads
895 * to fail to exit normally */
896 if (setresuid(uid
, uid
, uid
) < 0)
897 log_error_errno(r
, "Error: Failed to setresuid() in sd-pam: %m");
899 (void) ignore_signals(SIGPIPE
, -1);
901 /* Wait until our parent died. This will only work if
902 * the above setresuid() succeeds, otherwise the kernel
903 * will not allow unprivileged parents kill their privileged
904 * children this way. We rely on the control groups kill logic
905 * to do the rest for us. */
906 if (prctl(PR_SET_PDEATHSIG
, SIGTERM
) < 0)
909 /* Tell the parent that our setup is done. This is especially
910 * important regarding dropping privileges. Otherwise, unit
911 * setup might race against our setresuid(2) call. */
912 barrier_place(&barrier
);
914 /* Check if our parent process might already have
916 if (getppid() == parent_pid
) {
919 assert_se(sigemptyset(&ss
) >= 0);
920 assert_se(sigaddset(&ss
, SIGTERM
) >= 0);
923 if (sigwait(&ss
, &sig
) < 0) {
930 assert(sig
== SIGTERM
);
935 /* If our parent died we'll end the session */
936 if (getppid() != parent_pid
) {
937 pam_code
= pam_close_session(handle
, flags
);
938 if (pam_code
!= PAM_SUCCESS
)
945 pam_end(handle
, pam_code
| flags
);
949 barrier_set_role(&barrier
, BARRIER_PARENT
);
951 /* If the child was forked off successfully it will do all the
952 * cleanups, so forget about the handle here. */
955 /* Unblock SIGTERM again in the parent */
956 assert_se(sigprocmask(SIG_SETMASK
, &old_ss
, NULL
) >= 0);
958 /* We close the log explicitly here, since the PAM modules
959 * might have opened it, but we don't want this fd around. */
962 /* Synchronously wait for the child to initialize. We don't care for
963 * errors as we cannot recover. However, warn loudly if it happens. */
964 if (!barrier_place_and_sync(&barrier
))
965 log_error("PAM initialization failed");
973 if (pam_code
!= PAM_SUCCESS
) {
974 log_error("PAM failed: %s", pam_strerror(handle
, pam_code
));
975 err
= -EPERM
; /* PAM errors do not map to errno */
977 err
= log_error_errno(err
< 0 ? err
: errno
, "PAM failed: %m");
982 pam_code
= pam_close_session(handle
, flags
);
984 pam_end(handle
, pam_code
| flags
);
992 kill(pam_pid
, SIGTERM
);
993 kill(pam_pid
, SIGCONT
);
1000 static void rename_process_from_path(const char *path
) {
1001 char process_name
[11];
1005 /* This resulting string must fit in 10 chars (i.e. the length
1006 * of "/sbin/init") to look pretty in /bin/ps */
1010 rename_process("(...)");
1016 /* The end of the process name is usually more
1017 * interesting, since the first bit might just be
1023 process_name
[0] = '(';
1024 memcpy(process_name
+1, p
, l
);
1025 process_name
[1+l
] = ')';
1026 process_name
[1+l
+1] = 0;
1028 rename_process(process_name
);
1033 static int apply_seccomp(const ExecContext
*c
) {
1034 uint32_t negative_action
, action
;
1035 scmp_filter_ctx
*seccomp
;
1042 negative_action
= c
->syscall_errno
== 0 ? SCMP_ACT_KILL
: SCMP_ACT_ERRNO(c
->syscall_errno
);
1044 seccomp
= seccomp_init(c
->syscall_whitelist
? negative_action
: SCMP_ACT_ALLOW
);
1048 if (c
->syscall_archs
) {
1050 SET_FOREACH(id
, c
->syscall_archs
, i
) {
1051 r
= seccomp_arch_add(seccomp
, PTR_TO_UINT32(id
) - 1);
1059 r
= seccomp_add_secondary_archs(seccomp
);
1064 action
= c
->syscall_whitelist
? SCMP_ACT_ALLOW
: negative_action
;
1065 SET_FOREACH(id
, c
->syscall_filter
, i
) {
1066 r
= seccomp_rule_add(seccomp
, action
, PTR_TO_INT(id
) - 1, 0);
1071 r
= seccomp_attr_set(seccomp
, SCMP_FLTATR_CTL_NNP
, 0);
1075 r
= seccomp_load(seccomp
);
1078 seccomp_release(seccomp
);
1082 static int apply_address_families(const ExecContext
*c
) {
1083 scmp_filter_ctx
*seccomp
;
1089 seccomp
= seccomp_init(SCMP_ACT_ALLOW
);
1093 r
= seccomp_add_secondary_archs(seccomp
);
1097 if (c
->address_families_whitelist
) {
1098 int af
, first
= 0, last
= 0;
1101 /* If this is a whitelist, we first block the address
1102 * families that are out of range and then everything
1103 * that is not in the set. First, we find the lowest
1104 * and highest address family in the set. */
1106 SET_FOREACH(afp
, c
->address_families
, i
) {
1107 af
= PTR_TO_INT(afp
);
1109 if (af
<= 0 || af
>= af_max())
1112 if (first
== 0 || af
< first
)
1115 if (last
== 0 || af
> last
)
1119 assert((first
== 0) == (last
== 0));
1123 /* No entries in the valid range, block everything */
1124 r
= seccomp_rule_add(
1126 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1134 /* Block everything below the first entry */
1135 r
= seccomp_rule_add(
1137 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1140 SCMP_A0(SCMP_CMP_LT
, first
));
1144 /* Block everything above the last entry */
1145 r
= seccomp_rule_add(
1147 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1150 SCMP_A0(SCMP_CMP_GT
, last
));
1154 /* Block everything between the first and last
1156 for (af
= 1; af
< af_max(); af
++) {
1158 if (set_contains(c
->address_families
, INT_TO_PTR(af
)))
1161 r
= seccomp_rule_add(
1163 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1166 SCMP_A0(SCMP_CMP_EQ
, af
));
1175 /* If this is a blacklist, then generate one rule for
1176 * each address family that are then combined in OR
1179 SET_FOREACH(af
, c
->address_families
, i
) {
1181 r
= seccomp_rule_add(
1183 SCMP_ACT_ERRNO(EPROTONOSUPPORT
),
1186 SCMP_A0(SCMP_CMP_EQ
, PTR_TO_INT(af
)));
1192 r
= seccomp_attr_set(seccomp
, SCMP_FLTATR_CTL_NNP
, 0);
1196 r
= seccomp_load(seccomp
);
1199 seccomp_release(seccomp
);
1205 static void do_idle_pipe_dance(int idle_pipe
[4]) {
1209 idle_pipe
[1] = safe_close(idle_pipe
[1]);
1210 idle_pipe
[2] = safe_close(idle_pipe
[2]);
1212 if (idle_pipe
[0] >= 0) {
1215 r
= fd_wait_for_event(idle_pipe
[0], POLLHUP
, IDLE_TIMEOUT_USEC
);
1217 if (idle_pipe
[3] >= 0 && r
== 0 /* timeout */) {
1220 /* Signal systemd that we are bored and want to continue. */
1221 n
= write(idle_pipe
[3], "x", 1);
1223 /* Wait for systemd to react to the signal above. */
1224 fd_wait_for_event(idle_pipe
[0], POLLHUP
, IDLE_TIMEOUT2_USEC
);
1227 idle_pipe
[0] = safe_close(idle_pipe
[0]);
1231 idle_pipe
[3] = safe_close(idle_pipe
[3]);
1234 static int build_environment(
1235 const ExecContext
*c
,
1238 usec_t watchdog_usec
,
1240 const char *username
,
1244 _cleanup_strv_free_
char **our_env
= NULL
;
1251 our_env
= new0(char*, 11);
1256 _cleanup_free_
char *joined
= NULL
;
1258 if (asprintf(&x
, "LISTEN_PID="PID_FMT
, getpid()) < 0)
1260 our_env
[n_env
++] = x
;
1262 if (asprintf(&x
, "LISTEN_FDS=%u", n_fds
) < 0)
1264 our_env
[n_env
++] = x
;
1266 joined
= strv_join(fd_names
, ":");
1270 x
= strjoin("LISTEN_FDNAMES=", joined
, NULL
);
1273 our_env
[n_env
++] = x
;
1276 if (watchdog_usec
> 0) {
1277 if (asprintf(&x
, "WATCHDOG_PID="PID_FMT
, getpid()) < 0)
1279 our_env
[n_env
++] = x
;
1281 if (asprintf(&x
, "WATCHDOG_USEC="USEC_FMT
, watchdog_usec
) < 0)
1283 our_env
[n_env
++] = x
;
1287 x
= strappend("HOME=", home
);
1290 our_env
[n_env
++] = x
;
1294 x
= strappend("LOGNAME=", username
);
1297 our_env
[n_env
++] = x
;
1299 x
= strappend("USER=", username
);
1302 our_env
[n_env
++] = x
;
1306 x
= strappend("SHELL=", shell
);
1309 our_env
[n_env
++] = x
;
1312 if (is_terminal_input(c
->std_input
) ||
1313 c
->std_output
== EXEC_OUTPUT_TTY
||
1314 c
->std_error
== EXEC_OUTPUT_TTY
||
1317 x
= strdup(default_term_for_tty(tty_path(c
)));
1320 our_env
[n_env
++] = x
;
1323 our_env
[n_env
++] = NULL
;
1324 assert(n_env
<= 11);
1332 static bool exec_needs_mount_namespace(
1333 const ExecContext
*context
,
1334 const ExecParameters
*params
,
1335 ExecRuntime
*runtime
) {
1340 if (!strv_isempty(context
->read_write_dirs
) ||
1341 !strv_isempty(context
->read_only_dirs
) ||
1342 !strv_isempty(context
->inaccessible_dirs
))
1345 if (context
->mount_flags
!= 0)
1348 if (context
->private_tmp
&& runtime
&& (runtime
->tmp_dir
|| runtime
->var_tmp_dir
))
1351 if (params
->bus_endpoint_path
)
1354 if (context
->private_devices
||
1355 context
->protect_system
!= PROTECT_SYSTEM_NO
||
1356 context
->protect_home
!= PROTECT_HOME_NO
)
1362 static int close_remaining_fds(
1363 const ExecParameters
*params
,
1364 ExecRuntime
*runtime
,
1366 int *fds
, unsigned n_fds
) {
1368 unsigned n_dont_close
= 0;
1369 int dont_close
[n_fds
+ 7];
1373 if (params
->stdin_fd
>= 0)
1374 dont_close
[n_dont_close
++] = params
->stdin_fd
;
1375 if (params
->stdout_fd
>= 0)
1376 dont_close
[n_dont_close
++] = params
->stdout_fd
;
1377 if (params
->stderr_fd
>= 0)
1378 dont_close
[n_dont_close
++] = params
->stderr_fd
;
1381 dont_close
[n_dont_close
++] = socket_fd
;
1383 memcpy(dont_close
+ n_dont_close
, fds
, sizeof(int) * n_fds
);
1384 n_dont_close
+= n_fds
;
1387 if (params
->bus_endpoint_fd
>= 0)
1388 dont_close
[n_dont_close
++] = params
->bus_endpoint_fd
;
1391 if (runtime
->netns_storage_socket
[0] >= 0)
1392 dont_close
[n_dont_close
++] = runtime
->netns_storage_socket
[0];
1393 if (runtime
->netns_storage_socket
[1] >= 0)
1394 dont_close
[n_dont_close
++] = runtime
->netns_storage_socket
[1];
1397 return close_all_fds(dont_close
, n_dont_close
);
1400 static int exec_child(
1402 ExecCommand
*command
,
1403 const ExecContext
*context
,
1404 const ExecParameters
*params
,
1405 ExecRuntime
*runtime
,
1408 int *fds
, unsigned n_fds
,
1412 _cleanup_strv_free_
char **our_env
= NULL
, **pam_env
= NULL
, **final_env
= NULL
, **final_argv
= NULL
;
1413 _cleanup_free_
char *mac_selinux_context_net
= NULL
;
1414 const char *username
= NULL
, *home
= NULL
, *shell
= NULL
, *wd
;
1415 uid_t uid
= UID_INVALID
;
1416 gid_t gid
= GID_INVALID
;
1418 bool needs_mount_namespace
;
1424 assert(exit_status
);
1426 rename_process_from_path(command
->path
);
1428 /* We reset exactly these signals, since they are the
1429 * only ones we set to SIG_IGN in the main daemon. All
1430 * others we leave untouched because we set them to
1431 * SIG_DFL or a valid handler initially, both of which
1432 * will be demoted to SIG_DFL. */
1433 (void) default_signals(SIGNALS_CRASH_HANDLER
,
1434 SIGNALS_IGNORE
, -1);
1436 if (context
->ignore_sigpipe
)
1437 (void) ignore_signals(SIGPIPE
, -1);
1439 r
= reset_signal_mask();
1441 *exit_status
= EXIT_SIGNAL_MASK
;
1445 if (params
->idle_pipe
)
1446 do_idle_pipe_dance(params
->idle_pipe
);
1448 /* Close sockets very early to make sure we don't
1449 * block init reexecution because it cannot bind its
1454 r
= close_remaining_fds(params
, runtime
, socket_fd
, fds
, n_fds
);
1456 *exit_status
= EXIT_FDS
;
1460 if (!context
->same_pgrp
)
1462 *exit_status
= EXIT_SETSID
;
1466 exec_context_tty_reset(context
);
1468 if (params
->confirm_spawn
) {
1471 r
= ask_for_confirmation(&response
, argv
);
1472 if (r
== -ETIMEDOUT
)
1473 write_confirm_message("Confirmation question timed out, assuming positive response.\n");
1475 write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-r
));
1476 else if (response
== 's') {
1477 write_confirm_message("Skipping execution.\n");
1478 *exit_status
= EXIT_CONFIRM
;
1480 } else if (response
== 'n') {
1481 write_confirm_message("Failing execution.\n");
1487 if (context
->user
) {
1488 username
= context
->user
;
1489 r
= get_user_creds(&username
, &uid
, &gid
, &home
, &shell
);
1491 *exit_status
= EXIT_USER
;
1496 if (context
->group
) {
1497 const char *g
= context
->group
;
1499 r
= get_group_creds(&g
, &gid
);
1501 *exit_status
= EXIT_GROUP
;
1507 /* If a socket is connected to STDIN/STDOUT/STDERR, we
1508 * must sure to drop O_NONBLOCK */
1510 (void) fd_nonblock(socket_fd
, false);
1512 r
= setup_input(context
, params
, socket_fd
);
1514 *exit_status
= EXIT_STDIN
;
1518 r
= setup_output(unit
, context
, params
, STDOUT_FILENO
, socket_fd
, basename(command
->path
), uid
, gid
);
1520 *exit_status
= EXIT_STDOUT
;
1524 r
= setup_output(unit
, context
, params
, STDERR_FILENO
, socket_fd
, basename(command
->path
), uid
, gid
);
1526 *exit_status
= EXIT_STDERR
;
1530 if (params
->cgroup_path
) {
1531 r
= cg_attach_everywhere(params
->cgroup_supported
, params
->cgroup_path
, 0, NULL
, NULL
);
1533 *exit_status
= EXIT_CGROUP
;
1538 if (context
->oom_score_adjust_set
) {
1539 char t
[DECIMAL_STR_MAX(context
->oom_score_adjust
)];
1541 /* When we can't make this change due to EPERM, then
1542 * let's silently skip over it. User namespaces
1543 * prohibit write access to this file, and we
1544 * shouldn't trip up over that. */
1546 sprintf(t
, "%i", context
->oom_score_adjust
);
1547 r
= write_string_file("/proc/self/oom_score_adj", t
, 0);
1548 if (r
== -EPERM
|| r
== -EACCES
) {
1550 log_unit_debug_errno(unit
, r
, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
1553 *exit_status
= EXIT_OOM_ADJUST
;
1558 if (context
->nice_set
)
1559 if (setpriority(PRIO_PROCESS
, 0, context
->nice
) < 0) {
1560 *exit_status
= EXIT_NICE
;
1564 if (context
->cpu_sched_set
) {
1565 struct sched_param param
= {
1566 .sched_priority
= context
->cpu_sched_priority
,
1569 r
= sched_setscheduler(0,
1570 context
->cpu_sched_policy
|
1571 (context
->cpu_sched_reset_on_fork
?
1572 SCHED_RESET_ON_FORK
: 0),
1575 *exit_status
= EXIT_SETSCHEDULER
;
1580 if (context
->cpuset
)
1581 if (sched_setaffinity(0, CPU_ALLOC_SIZE(context
->cpuset_ncpus
), context
->cpuset
) < 0) {
1582 *exit_status
= EXIT_CPUAFFINITY
;
1586 if (context
->ioprio_set
)
1587 if (ioprio_set(IOPRIO_WHO_PROCESS
, 0, context
->ioprio
) < 0) {
1588 *exit_status
= EXIT_IOPRIO
;
1592 if (context
->timer_slack_nsec
!= NSEC_INFINITY
)
1593 if (prctl(PR_SET_TIMERSLACK
, context
->timer_slack_nsec
) < 0) {
1594 *exit_status
= EXIT_TIMERSLACK
;
1598 if (context
->personality
!= PERSONALITY_INVALID
)
1599 if (personality(context
->personality
) < 0) {
1600 *exit_status
= EXIT_PERSONALITY
;
1604 if (context
->utmp_id
)
1605 utmp_put_init_process(context
->utmp_id
, getpid(), getsid(0), context
->tty_path
,
1606 context
->utmp_mode
== EXEC_UTMP_INIT
? INIT_PROCESS
:
1607 context
->utmp_mode
== EXEC_UTMP_LOGIN
? LOGIN_PROCESS
:
1609 username
? "root" : context
->user
);
1611 if (context
->user
&& is_terminal_input(context
->std_input
)) {
1612 r
= chown_terminal(STDIN_FILENO
, uid
);
1614 *exit_status
= EXIT_STDIN
;
1619 if (params
->bus_endpoint_fd
>= 0 && context
->bus_endpoint
) {
1620 uid_t ep_uid
= (uid
== UID_INVALID
) ? 0 : uid
;
1622 r
= bus_kernel_set_endpoint_policy(params
->bus_endpoint_fd
, ep_uid
, context
->bus_endpoint
);
1624 *exit_status
= EXIT_BUS_ENDPOINT
;
1629 /* If delegation is enabled we'll pass ownership of the cgroup
1630 * (but only in systemd's own controller hierarchy!) to the
1631 * user of the new process. */
1632 if (params
->cgroup_path
&& context
->user
&& params
->cgroup_delegate
) {
1633 r
= cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER
, params
->cgroup_path
, 0644, uid
, gid
);
1635 *exit_status
= EXIT_CGROUP
;
1640 r
= cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER
, params
->cgroup_path
, 0755, uid
, gid
);
1642 *exit_status
= EXIT_CGROUP
;
1647 if (!strv_isempty(context
->runtime_directory
) && params
->runtime_prefix
) {
1650 STRV_FOREACH(rt
, context
->runtime_directory
) {
1651 _cleanup_free_
char *p
;
1653 p
= strjoin(params
->runtime_prefix
, "/", *rt
, NULL
);
1655 *exit_status
= EXIT_RUNTIME_DIRECTORY
;
1659 r
= mkdir_p_label(p
, context
->runtime_directory_mode
);
1661 *exit_status
= EXIT_RUNTIME_DIRECTORY
;
1665 r
= chmod_and_chown(p
, context
->runtime_directory_mode
, uid
, gid
);
1667 *exit_status
= EXIT_RUNTIME_DIRECTORY
;
1673 umask(context
->umask
);
1675 if (params
->apply_permissions
) {
1676 r
= enforce_groups(context
, username
, gid
);
1678 *exit_status
= EXIT_GROUP
;
1682 if (context
->smack_process_label
) {
1683 r
= mac_smack_apply_pid(0, context
->smack_process_label
);
1685 *exit_status
= EXIT_SMACK_PROCESS_LABEL
;
1689 #ifdef SMACK_DEFAULT_PROCESS_LABEL
1691 _cleanup_free_
char *exec_label
= NULL
;
1693 r
= mac_smack_read(command
->path
, SMACK_ATTR_EXEC
, &exec_label
);
1694 if (r
< 0 && r
!= -ENODATA
&& r
!= -EOPNOTSUPP
) {
1695 *exit_status
= EXIT_SMACK_PROCESS_LABEL
;
1699 r
= mac_smack_apply_pid(0, exec_label
? : SMACK_DEFAULT_PROCESS_LABEL
);
1701 *exit_status
= EXIT_SMACK_PROCESS_LABEL
;
1708 if (context
->pam_name
&& username
) {
1709 r
= setup_pam(context
->pam_name
, username
, uid
, context
->tty_path
, &pam_env
, fds
, n_fds
);
1711 *exit_status
= EXIT_PAM
;
1718 if (context
->private_network
&& runtime
&& runtime
->netns_storage_socket
[0] >= 0) {
1719 r
= setup_netns(runtime
->netns_storage_socket
);
1721 *exit_status
= EXIT_NETWORK
;
1726 needs_mount_namespace
= exec_needs_mount_namespace(context
, params
, runtime
);
1728 if (needs_mount_namespace
) {
1729 char *tmp
= NULL
, *var
= NULL
;
1731 /* The runtime struct only contains the parent
1732 * of the private /tmp, which is
1733 * non-accessible to world users. Inside of it
1734 * there's a /tmp that is sticky, and that's
1735 * the one we want to use here. */
1737 if (context
->private_tmp
&& runtime
) {
1738 if (runtime
->tmp_dir
)
1739 tmp
= strjoina(runtime
->tmp_dir
, "/tmp");
1740 if (runtime
->var_tmp_dir
)
1741 var
= strjoina(runtime
->var_tmp_dir
, "/tmp");
1744 r
= setup_namespace(
1745 params
->apply_chroot
? context
->root_directory
: NULL
,
1746 context
->read_write_dirs
,
1747 context
->read_only_dirs
,
1748 context
->inaccessible_dirs
,
1751 params
->bus_endpoint_path
,
1752 context
->private_devices
,
1753 context
->protect_home
,
1754 context
->protect_system
,
1755 context
->mount_flags
);
1757 /* If we couldn't set up the namespace this is
1758 * probably due to a missing capability. In this case,
1759 * silently proceeed. */
1760 if (r
== -EPERM
|| r
== -EACCES
) {
1762 log_unit_debug_errno(unit
, r
, "Failed to set up namespace, assuming containerized execution, ignoring: %m");
1765 *exit_status
= EXIT_NAMESPACE
;
1770 if (context
->working_directory_home
)
1772 else if (context
->working_directory
)
1773 wd
= context
->working_directory
;
1777 if (params
->apply_chroot
) {
1778 if (!needs_mount_namespace
&& context
->root_directory
)
1779 if (chroot(context
->root_directory
) < 0) {
1780 *exit_status
= EXIT_CHROOT
;
1784 if (chdir(wd
) < 0 &&
1785 !context
->working_directory_missing_ok
) {
1786 *exit_status
= EXIT_CHDIR
;
1792 d
= strjoina(strempty(context
->root_directory
), "/", strempty(wd
));
1794 !context
->working_directory_missing_ok
) {
1795 *exit_status
= EXIT_CHDIR
;
1801 if (params
->apply_permissions
&& mac_selinux_use() && params
->selinux_context_net
&& socket_fd
>= 0) {
1802 r
= mac_selinux_get_child_mls_label(socket_fd
, command
->path
, context
->selinux_context
, &mac_selinux_context_net
);
1804 *exit_status
= EXIT_SELINUX_CONTEXT
;
1810 /* We repeat the fd closing here, to make sure that
1811 * nothing is leaked from the PAM modules. Note that
1812 * we are more aggressive this time since socket_fd
1813 * and the netns fds we don't need anymore. The custom
1814 * endpoint fd was needed to upload the policy and can
1815 * now be closed as well. */
1816 r
= close_all_fds(fds
, n_fds
);
1818 r
= shift_fds(fds
, n_fds
);
1820 r
= flags_fds(fds
, n_fds
, context
->non_blocking
);
1822 *exit_status
= EXIT_FDS
;
1826 if (params
->apply_permissions
) {
1828 for (i
= 0; i
< _RLIMIT_MAX
; i
++) {
1829 if (!context
->rlimit
[i
])
1832 if (setrlimit_closest(i
, context
->rlimit
[i
]) < 0) {
1833 *exit_status
= EXIT_LIMITS
;
1838 if (context
->capability_bounding_set_drop
) {
1839 r
= capability_bounding_set_drop(context
->capability_bounding_set_drop
, false);
1841 *exit_status
= EXIT_CAPABILITIES
;
1846 if (context
->user
) {
1847 r
= enforce_user(context
, uid
);
1849 *exit_status
= EXIT_USER
;
1854 /* PR_GET_SECUREBITS is not privileged, while
1855 * PR_SET_SECUREBITS is. So to suppress
1856 * potential EPERMs we'll try not to call
1857 * PR_SET_SECUREBITS unless necessary. */
1858 if (prctl(PR_GET_SECUREBITS
) != context
->secure_bits
)
1859 if (prctl(PR_SET_SECUREBITS
, context
->secure_bits
) < 0) {
1860 *exit_status
= EXIT_SECUREBITS
;
1864 if (context
->capabilities
)
1865 if (cap_set_proc(context
->capabilities
) < 0) {
1866 *exit_status
= EXIT_CAPABILITIES
;
1870 if (context
->no_new_privileges
)
1871 if (prctl(PR_SET_NO_NEW_PRIVS
, 1, 0, 0, 0) < 0) {
1872 *exit_status
= EXIT_NO_NEW_PRIVILEGES
;
1877 if (context
->address_families_whitelist
||
1878 !set_isempty(context
->address_families
)) {
1879 r
= apply_address_families(context
);
1881 *exit_status
= EXIT_ADDRESS_FAMILIES
;
1886 if (context
->syscall_whitelist
||
1887 !set_isempty(context
->syscall_filter
) ||
1888 !set_isempty(context
->syscall_archs
)) {
1889 r
= apply_seccomp(context
);
1891 *exit_status
= EXIT_SECCOMP
;
1898 if (mac_selinux_use()) {
1899 char *exec_context
= mac_selinux_context_net
?: context
->selinux_context
;
1902 r
= setexeccon(exec_context
);
1904 *exit_status
= EXIT_SELINUX_CONTEXT
;
1911 #ifdef HAVE_APPARMOR
1912 if (context
->apparmor_profile
&& mac_apparmor_use()) {
1913 r
= aa_change_onexec(context
->apparmor_profile
);
1914 if (r
< 0 && !context
->apparmor_profile_ignore
) {
1915 *exit_status
= EXIT_APPARMOR_PROFILE
;
1922 r
= build_environment(context
, n_fds
, params
->fd_names
, params
->watchdog_usec
, home
, username
, shell
, &our_env
);
1924 *exit_status
= EXIT_MEMORY
;
1928 final_env
= strv_env_merge(5,
1929 params
->environment
,
1931 context
->environment
,
1936 *exit_status
= EXIT_MEMORY
;
1940 final_argv
= replace_env_argv(argv
, final_env
);
1942 *exit_status
= EXIT_MEMORY
;
1946 final_env
= strv_env_clean(final_env
);
1948 if (_unlikely_(log_get_max_level() >= LOG_DEBUG
)) {
1949 _cleanup_free_
char *line
;
1951 line
= exec_command_line(final_argv
);
1954 log_struct(LOG_DEBUG
,
1956 "EXECUTABLE=%s", command
->path
,
1957 LOG_UNIT_MESSAGE(unit
, "Executing: %s", line
),
1963 execve(command
->path
, final_argv
, final_env
);
1964 *exit_status
= EXIT_EXEC
;
1968 int exec_spawn(Unit
*unit
,
1969 ExecCommand
*command
,
1970 const ExecContext
*context
,
1971 const ExecParameters
*params
,
1972 ExecRuntime
*runtime
,
1975 _cleanup_strv_free_
char **files_env
= NULL
;
1976 int *fds
= NULL
; unsigned n_fds
= 0;
1977 _cleanup_free_
char *line
= NULL
;
1987 assert(params
->fds
|| params
->n_fds
<= 0);
1989 if (context
->std_input
== EXEC_INPUT_SOCKET
||
1990 context
->std_output
== EXEC_OUTPUT_SOCKET
||
1991 context
->std_error
== EXEC_OUTPUT_SOCKET
) {
1993 if (params
->n_fds
!= 1) {
1994 log_unit_error(unit
, "Got more than one socket.");
1998 socket_fd
= params
->fds
[0];
2002 n_fds
= params
->n_fds
;
2005 r
= exec_context_load_environment(unit
, context
, &files_env
);
2007 return log_unit_error_errno(unit
, r
, "Failed to load environment files: %m");
2009 argv
= params
->argv
?: command
->argv
;
2010 line
= exec_command_line(argv
);
2014 log_struct(LOG_DEBUG
,
2016 LOG_UNIT_MESSAGE(unit
, "About to execute: %s", line
),
2017 "EXECUTABLE=%s", command
->path
,
2021 return log_unit_error_errno(unit
, r
, "Failed to fork: %m");
2026 r
= exec_child(unit
,
2038 log_struct_errno(LOG_ERR
, r
,
2039 LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED
),
2041 LOG_UNIT_MESSAGE(unit
, "Failed at step %s spawning %s: %m",
2042 exit_status_to_string(exit_status
, EXIT_STATUS_SYSTEMD
),
2044 "EXECUTABLE=%s", command
->path
,
2051 log_unit_debug(unit
, "Forked %s as "PID_FMT
, command
->path
, pid
);
2053 /* We add the new process to the cgroup both in the child (so
2054 * that we can be sure that no user code is ever executed
2055 * outside of the cgroup) and in the parent (so that we can be
2056 * sure that when we kill the cgroup the process will be
2058 if (params
->cgroup_path
)
2059 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER
, params
->cgroup_path
, pid
);
2061 exec_status_start(&command
->exec_status
, pid
);
2067 void exec_context_init(ExecContext
*c
) {
2071 c
->ioprio
= IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE
, 0);
2072 c
->cpu_sched_policy
= SCHED_OTHER
;
2073 c
->syslog_priority
= LOG_DAEMON
|LOG_INFO
;
2074 c
->syslog_level_prefix
= true;
2075 c
->ignore_sigpipe
= true;
2076 c
->timer_slack_nsec
= NSEC_INFINITY
;
2077 c
->personality
= PERSONALITY_INVALID
;
2078 c
->runtime_directory_mode
= 0755;
2081 void exec_context_done(ExecContext
*c
) {
2086 c
->environment
= strv_free(c
->environment
);
2087 c
->environment_files
= strv_free(c
->environment_files
);
2089 for (l
= 0; l
< ELEMENTSOF(c
->rlimit
); l
++)
2090 c
->rlimit
[l
] = mfree(c
->rlimit
[l
]);
2092 c
->working_directory
= mfree(c
->working_directory
);
2093 c
->root_directory
= mfree(c
->root_directory
);
2094 c
->tty_path
= mfree(c
->tty_path
);
2095 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
2096 c
->user
= mfree(c
->user
);
2097 c
->group
= mfree(c
->group
);
2099 c
->supplementary_groups
= strv_free(c
->supplementary_groups
);
2101 c
->pam_name
= mfree(c
->pam_name
);
2103 if (c
->capabilities
) {
2104 cap_free(c
->capabilities
);
2105 c
->capabilities
= NULL
;
2108 c
->read_only_dirs
= strv_free(c
->read_only_dirs
);
2109 c
->read_write_dirs
= strv_free(c
->read_write_dirs
);
2110 c
->inaccessible_dirs
= strv_free(c
->inaccessible_dirs
);
2113 CPU_FREE(c
->cpuset
);
2115 c
->utmp_id
= mfree(c
->utmp_id
);
2116 c
->selinux_context
= mfree(c
->selinux_context
);
2117 c
->apparmor_profile
= mfree(c
->apparmor_profile
);
2119 c
->syscall_filter
= set_free(c
->syscall_filter
);
2120 c
->syscall_archs
= set_free(c
->syscall_archs
);
2121 c
->address_families
= set_free(c
->address_families
);
2123 c
->runtime_directory
= strv_free(c
->runtime_directory
);
2125 bus_endpoint_free(c
->bus_endpoint
);
2126 c
->bus_endpoint
= NULL
;
2129 int exec_context_destroy_runtime_directory(ExecContext
*c
, const char *runtime_prefix
) {
2134 if (!runtime_prefix
)
2137 STRV_FOREACH(i
, c
->runtime_directory
) {
2138 _cleanup_free_
char *p
;
2140 p
= strjoin(runtime_prefix
, "/", *i
, NULL
);
2144 /* We execute this synchronously, since we need to be
2145 * sure this is gone when we start the service
2147 (void) rm_rf(p
, REMOVE_ROOT
);
2153 void exec_command_done(ExecCommand
*c
) {
2156 c
->path
= mfree(c
->path
);
2158 c
->argv
= strv_free(c
->argv
);
2161 void exec_command_done_array(ExecCommand
*c
, unsigned n
) {
2164 for (i
= 0; i
< n
; i
++)
2165 exec_command_done(c
+i
);
2168 ExecCommand
* exec_command_free_list(ExecCommand
*c
) {
2172 LIST_REMOVE(command
, c
, i
);
2173 exec_command_done(i
);
2180 void exec_command_free_array(ExecCommand
**c
, unsigned n
) {
2183 for (i
= 0; i
< n
; i
++)
2184 c
[i
] = exec_command_free_list(c
[i
]);
2187 typedef struct InvalidEnvInfo
{
2192 static void invalid_env(const char *p
, void *userdata
) {
2193 InvalidEnvInfo
*info
= userdata
;
2195 log_unit_error(info
->unit
, "Ignoring invalid environment assignment '%s': %s", p
, info
->path
);
2198 int exec_context_load_environment(Unit
*unit
, const ExecContext
*c
, char ***l
) {
2199 char **i
, **r
= NULL
;
2204 STRV_FOREACH(i
, c
->environment_files
) {
2207 bool ignore
= false;
2209 _cleanup_globfree_ glob_t pglob
= {};
2219 if (!path_is_absolute(fn
)) {
2227 /* Filename supports globbing, take all matching files */
2229 if (glob(fn
, 0, NULL
, &pglob
) != 0) {
2234 return errno
? -errno
: -EINVAL
;
2236 count
= pglob
.gl_pathc
;
2244 for (n
= 0; n
< count
; n
++) {
2245 k
= load_env_file(NULL
, pglob
.gl_pathv
[n
], NULL
, &p
);
2253 /* Log invalid environment variables with filename */
2255 InvalidEnvInfo info
= {
2257 .path
= pglob
.gl_pathv
[n
]
2260 p
= strv_env_clean_with_callback(p
, invalid_env
, &info
);
2268 m
= strv_env_merge(2, r
, p
);
2284 static bool tty_may_match_dev_console(const char *tty
) {
2285 _cleanup_free_
char *active
= NULL
;
2288 if (startswith(tty
, "/dev/"))
2291 /* trivial identity? */
2292 if (streq(tty
, "console"))
2295 console
= resolve_dev_console(&active
);
2296 /* if we could not resolve, assume it may */
2300 /* "tty0" means the active VC, so it may be the same sometimes */
2301 return streq(console
, tty
) || (streq(console
, "tty0") && tty_is_vc(tty
));
2304 bool exec_context_may_touch_console(ExecContext
*ec
) {
2305 return (ec
->tty_reset
|| ec
->tty_vhangup
|| ec
->tty_vt_disallocate
||
2306 is_terminal_input(ec
->std_input
) ||
2307 is_terminal_output(ec
->std_output
) ||
2308 is_terminal_output(ec
->std_error
)) &&
2309 tty_may_match_dev_console(tty_path(ec
));
2312 static void strv_fprintf(FILE *f
, char **l
) {
2318 fprintf(f
, " %s", *g
);
2321 void exec_context_dump(ExecContext
*c
, FILE* f
, const char *prefix
) {
2328 prefix
= strempty(prefix
);
2332 "%sWorkingDirectory: %s\n"
2333 "%sRootDirectory: %s\n"
2334 "%sNonBlocking: %s\n"
2335 "%sPrivateTmp: %s\n"
2336 "%sPrivateNetwork: %s\n"
2337 "%sPrivateDevices: %s\n"
2338 "%sProtectHome: %s\n"
2339 "%sProtectSystem: %s\n"
2340 "%sIgnoreSIGPIPE: %s\n",
2342 prefix
, c
->working_directory
? c
->working_directory
: "/",
2343 prefix
, c
->root_directory
? c
->root_directory
: "/",
2344 prefix
, yes_no(c
->non_blocking
),
2345 prefix
, yes_no(c
->private_tmp
),
2346 prefix
, yes_no(c
->private_network
),
2347 prefix
, yes_no(c
->private_devices
),
2348 prefix
, protect_home_to_string(c
->protect_home
),
2349 prefix
, protect_system_to_string(c
->protect_system
),
2350 prefix
, yes_no(c
->ignore_sigpipe
));
2352 STRV_FOREACH(e
, c
->environment
)
2353 fprintf(f
, "%sEnvironment: %s\n", prefix
, *e
);
2355 STRV_FOREACH(e
, c
->environment_files
)
2356 fprintf(f
, "%sEnvironmentFile: %s\n", prefix
, *e
);
2358 fprintf(f
, "%sRuntimeDirectoryMode: %04o\n", prefix
, c
->runtime_directory_mode
);
2360 STRV_FOREACH(d
, c
->runtime_directory
)
2361 fprintf(f
, "%sRuntimeDirectory: %s\n", prefix
, *d
);
2368 if (c
->oom_score_adjust_set
)
2370 "%sOOMScoreAdjust: %i\n",
2371 prefix
, c
->oom_score_adjust
);
2373 for (i
= 0; i
< RLIM_NLIMITS
; i
++)
2375 fprintf(f
, "%s%s: "RLIM_FMT
"\n",
2376 prefix
, rlimit_to_string(i
), c
->rlimit
[i
]->rlim_max
);
2378 if (c
->ioprio_set
) {
2379 _cleanup_free_
char *class_str
= NULL
;
2381 ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c
->ioprio
), &class_str
);
2383 "%sIOSchedulingClass: %s\n"
2384 "%sIOPriority: %i\n",
2385 prefix
, strna(class_str
),
2386 prefix
, (int) IOPRIO_PRIO_DATA(c
->ioprio
));
2389 if (c
->cpu_sched_set
) {
2390 _cleanup_free_
char *policy_str
= NULL
;
2392 sched_policy_to_string_alloc(c
->cpu_sched_policy
, &policy_str
);
2394 "%sCPUSchedulingPolicy: %s\n"
2395 "%sCPUSchedulingPriority: %i\n"
2396 "%sCPUSchedulingResetOnFork: %s\n",
2397 prefix
, strna(policy_str
),
2398 prefix
, c
->cpu_sched_priority
,
2399 prefix
, yes_no(c
->cpu_sched_reset_on_fork
));
2403 fprintf(f
, "%sCPUAffinity:", prefix
);
2404 for (i
= 0; i
< c
->cpuset_ncpus
; i
++)
2405 if (CPU_ISSET_S(i
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
), c
->cpuset
))
2406 fprintf(f
, " %u", i
);
2410 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
2411 fprintf(f
, "%sTimerSlackNSec: "NSEC_FMT
"\n", prefix
, c
->timer_slack_nsec
);
2414 "%sStandardInput: %s\n"
2415 "%sStandardOutput: %s\n"
2416 "%sStandardError: %s\n",
2417 prefix
, exec_input_to_string(c
->std_input
),
2418 prefix
, exec_output_to_string(c
->std_output
),
2419 prefix
, exec_output_to_string(c
->std_error
));
2425 "%sTTYVHangup: %s\n"
2426 "%sTTYVTDisallocate: %s\n",
2427 prefix
, c
->tty_path
,
2428 prefix
, yes_no(c
->tty_reset
),
2429 prefix
, yes_no(c
->tty_vhangup
),
2430 prefix
, yes_no(c
->tty_vt_disallocate
));
2432 if (c
->std_output
== EXEC_OUTPUT_SYSLOG
||
2433 c
->std_output
== EXEC_OUTPUT_KMSG
||
2434 c
->std_output
== EXEC_OUTPUT_JOURNAL
||
2435 c
->std_output
== EXEC_OUTPUT_SYSLOG_AND_CONSOLE
||
2436 c
->std_output
== EXEC_OUTPUT_KMSG_AND_CONSOLE
||
2437 c
->std_output
== EXEC_OUTPUT_JOURNAL_AND_CONSOLE
||
2438 c
->std_error
== EXEC_OUTPUT_SYSLOG
||
2439 c
->std_error
== EXEC_OUTPUT_KMSG
||
2440 c
->std_error
== EXEC_OUTPUT_JOURNAL
||
2441 c
->std_error
== EXEC_OUTPUT_SYSLOG_AND_CONSOLE
||
2442 c
->std_error
== EXEC_OUTPUT_KMSG_AND_CONSOLE
||
2443 c
->std_error
== EXEC_OUTPUT_JOURNAL_AND_CONSOLE
) {
2445 _cleanup_free_
char *fac_str
= NULL
, *lvl_str
= NULL
;
2447 log_facility_unshifted_to_string_alloc(c
->syslog_priority
>> 3, &fac_str
);
2448 log_level_to_string_alloc(LOG_PRI(c
->syslog_priority
), &lvl_str
);
2451 "%sSyslogFacility: %s\n"
2452 "%sSyslogLevel: %s\n",
2453 prefix
, strna(fac_str
),
2454 prefix
, strna(lvl_str
));
2457 if (c
->capabilities
) {
2458 _cleanup_cap_free_charp_
char *t
;
2460 t
= cap_to_text(c
->capabilities
, NULL
);
2462 fprintf(f
, "%sCapabilities: %s\n", prefix
, t
);
2466 fprintf(f
, "%sSecure Bits:%s%s%s%s%s%s\n",
2468 (c
->secure_bits
& 1<<SECURE_KEEP_CAPS
) ? " keep-caps" : "",
2469 (c
->secure_bits
& 1<<SECURE_KEEP_CAPS_LOCKED
) ? " keep-caps-locked" : "",
2470 (c
->secure_bits
& 1<<SECURE_NO_SETUID_FIXUP
) ? " no-setuid-fixup" : "",
2471 (c
->secure_bits
& 1<<SECURE_NO_SETUID_FIXUP_LOCKED
) ? " no-setuid-fixup-locked" : "",
2472 (c
->secure_bits
& 1<<SECURE_NOROOT
) ? " noroot" : "",
2473 (c
->secure_bits
& 1<<SECURE_NOROOT_LOCKED
) ? "noroot-locked" : "");
2475 if (c
->capability_bounding_set_drop
) {
2477 fprintf(f
, "%sCapabilityBoundingSet:", prefix
);
2479 for (l
= 0; l
<= cap_last_cap(); l
++)
2480 if (!(c
->capability_bounding_set_drop
& ((uint64_t) 1ULL << (uint64_t) l
)))
2481 fprintf(f
, " %s", strna(capability_to_name(l
)));
2487 fprintf(f
, "%sUser: %s\n", prefix
, c
->user
);
2489 fprintf(f
, "%sGroup: %s\n", prefix
, c
->group
);
2491 if (strv_length(c
->supplementary_groups
) > 0) {
2492 fprintf(f
, "%sSupplementaryGroups:", prefix
);
2493 strv_fprintf(f
, c
->supplementary_groups
);
2498 fprintf(f
, "%sPAMName: %s\n", prefix
, c
->pam_name
);
2500 if (strv_length(c
->read_write_dirs
) > 0) {
2501 fprintf(f
, "%sReadWriteDirs:", prefix
);
2502 strv_fprintf(f
, c
->read_write_dirs
);
2506 if (strv_length(c
->read_only_dirs
) > 0) {
2507 fprintf(f
, "%sReadOnlyDirs:", prefix
);
2508 strv_fprintf(f
, c
->read_only_dirs
);
2512 if (strv_length(c
->inaccessible_dirs
) > 0) {
2513 fprintf(f
, "%sInaccessibleDirs:", prefix
);
2514 strv_fprintf(f
, c
->inaccessible_dirs
);
2520 "%sUtmpIdentifier: %s\n",
2521 prefix
, c
->utmp_id
);
2523 if (c
->selinux_context
)
2525 "%sSELinuxContext: %s%s\n",
2526 prefix
, c
->selinux_context_ignore
? "-" : "", c
->selinux_context
);
2528 if (c
->personality
!= PERSONALITY_INVALID
)
2530 "%sPersonality: %s\n",
2531 prefix
, strna(personality_to_string(c
->personality
)));
2533 if (c
->syscall_filter
) {
2541 "%sSystemCallFilter: ",
2544 if (!c
->syscall_whitelist
)
2548 SET_FOREACH(id
, c
->syscall_filter
, j
) {
2549 _cleanup_free_
char *name
= NULL
;
2556 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
2557 fputs(strna(name
), f
);
2564 if (c
->syscall_archs
) {
2571 "%sSystemCallArchitectures:",
2575 SET_FOREACH(id
, c
->syscall_archs
, j
)
2576 fprintf(f
, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1)));
2581 if (c
->syscall_errno
!= 0)
2583 "%sSystemCallErrorNumber: %s\n",
2584 prefix
, strna(errno_to_name(c
->syscall_errno
)));
2586 if (c
->apparmor_profile
)
2588 "%sAppArmorProfile: %s%s\n",
2589 prefix
, c
->apparmor_profile_ignore
? "-" : "", c
->apparmor_profile
);
2592 bool exec_context_maintains_privileges(ExecContext
*c
) {
2595 /* Returns true if the process forked off would run run under
2596 * an unchanged UID or as root. */
2601 if (streq(c
->user
, "root") || streq(c
->user
, "0"))
2607 void exec_status_start(ExecStatus
*s
, pid_t pid
) {
2612 dual_timestamp_get(&s
->start_timestamp
);
2615 void exec_status_exit(ExecStatus
*s
, ExecContext
*context
, pid_t pid
, int code
, int status
) {
2618 if (s
->pid
&& s
->pid
!= pid
)
2622 dual_timestamp_get(&s
->exit_timestamp
);
2628 if (context
->utmp_id
)
2629 utmp_put_dead_process(context
->utmp_id
, pid
, code
, status
);
2631 exec_context_tty_reset(context
);
2635 void exec_status_dump(ExecStatus
*s
, FILE *f
, const char *prefix
) {
2636 char buf
[FORMAT_TIMESTAMP_MAX
];
2644 prefix
= strempty(prefix
);
2647 "%sPID: "PID_FMT
"\n",
2650 if (s
->start_timestamp
.realtime
> 0)
2652 "%sStart Timestamp: %s\n",
2653 prefix
, format_timestamp(buf
, sizeof(buf
), s
->start_timestamp
.realtime
));
2655 if (s
->exit_timestamp
.realtime
> 0)
2657 "%sExit Timestamp: %s\n"
2659 "%sExit Status: %i\n",
2660 prefix
, format_timestamp(buf
, sizeof(buf
), s
->exit_timestamp
.realtime
),
2661 prefix
, sigchld_code_to_string(s
->code
),
2665 char *exec_command_line(char **argv
) {
2673 STRV_FOREACH(a
, argv
)
2676 if (!(n
= new(char, k
)))
2680 STRV_FOREACH(a
, argv
) {
2687 if (strpbrk(*a
, WHITESPACE
)) {
2698 /* FIXME: this doesn't really handle arguments that have
2699 * spaces and ticks in them */
2704 void exec_command_dump(ExecCommand
*c
, FILE *f
, const char *prefix
) {
2705 _cleanup_free_
char *cmd
= NULL
;
2706 const char *prefix2
;
2711 prefix
= strempty(prefix
);
2712 prefix2
= strjoina(prefix
, "\t");
2714 cmd
= exec_command_line(c
->argv
);
2716 "%sCommand Line: %s\n",
2717 prefix
, cmd
? cmd
: strerror(ENOMEM
));
2719 exec_status_dump(&c
->exec_status
, f
, prefix2
);
2722 void exec_command_dump_list(ExecCommand
*c
, FILE *f
, const char *prefix
) {
2725 prefix
= strempty(prefix
);
2727 LIST_FOREACH(command
, c
, c
)
2728 exec_command_dump(c
, f
, prefix
);
2731 void exec_command_append_list(ExecCommand
**l
, ExecCommand
*e
) {
2738 /* It's kind of important, that we keep the order here */
2739 LIST_FIND_TAIL(command
, *l
, end
);
2740 LIST_INSERT_AFTER(command
, *l
, end
, e
);
2745 int exec_command_set(ExecCommand
*c
, const char *path
, ...) {
2753 l
= strv_new_ap(path
, ap
);
2774 int exec_command_append(ExecCommand
*c
, const char *path
, ...) {
2775 _cleanup_strv_free_
char **l
= NULL
;
2783 l
= strv_new_ap(path
, ap
);
2789 r
= strv_extend_strv(&c
->argv
, l
, false);
2797 static int exec_runtime_allocate(ExecRuntime
**rt
) {
2802 *rt
= new0(ExecRuntime
, 1);
2807 (*rt
)->netns_storage_socket
[0] = (*rt
)->netns_storage_socket
[1] = -1;
2812 int exec_runtime_make(ExecRuntime
**rt
, ExecContext
*c
, const char *id
) {
2822 if (!c
->private_network
&& !c
->private_tmp
)
2825 r
= exec_runtime_allocate(rt
);
2829 if (c
->private_network
&& (*rt
)->netns_storage_socket
[0] < 0) {
2830 if (socketpair(AF_UNIX
, SOCK_DGRAM
, 0, (*rt
)->netns_storage_socket
) < 0)
2834 if (c
->private_tmp
&& !(*rt
)->tmp_dir
) {
2835 r
= setup_tmp_dirs(id
, &(*rt
)->tmp_dir
, &(*rt
)->var_tmp_dir
);
2843 ExecRuntime
*exec_runtime_ref(ExecRuntime
*r
) {
2845 assert(r
->n_ref
> 0);
2851 ExecRuntime
*exec_runtime_unref(ExecRuntime
*r
) {
2856 assert(r
->n_ref
> 0);
2863 free(r
->var_tmp_dir
);
2864 safe_close_pair(r
->netns_storage_socket
);
2870 int exec_runtime_serialize(Unit
*u
, ExecRuntime
*rt
, FILE *f
, FDSet
*fds
) {
2879 unit_serialize_item(u
, f
, "tmp-dir", rt
->tmp_dir
);
2881 if (rt
->var_tmp_dir
)
2882 unit_serialize_item(u
, f
, "var-tmp-dir", rt
->var_tmp_dir
);
2884 if (rt
->netns_storage_socket
[0] >= 0) {
2887 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[0]);
2891 unit_serialize_item_format(u
, f
, "netns-socket-0", "%i", copy
);
2894 if (rt
->netns_storage_socket
[1] >= 0) {
2897 copy
= fdset_put_dup(fds
, rt
->netns_storage_socket
[1]);
2901 unit_serialize_item_format(u
, f
, "netns-socket-1", "%i", copy
);
2907 int exec_runtime_deserialize_item(Unit
*u
, ExecRuntime
**rt
, const char *key
, const char *value
, FDSet
*fds
) {
2914 if (streq(key
, "tmp-dir")) {
2917 r
= exec_runtime_allocate(rt
);
2921 copy
= strdup(value
);
2925 free((*rt
)->tmp_dir
);
2926 (*rt
)->tmp_dir
= copy
;
2928 } else if (streq(key
, "var-tmp-dir")) {
2931 r
= exec_runtime_allocate(rt
);
2935 copy
= strdup(value
);
2939 free((*rt
)->var_tmp_dir
);
2940 (*rt
)->var_tmp_dir
= copy
;
2942 } else if (streq(key
, "netns-socket-0")) {
2945 r
= exec_runtime_allocate(rt
);
2949 if (safe_atoi(value
, &fd
) < 0 || !fdset_contains(fds
, fd
))
2950 log_unit_debug(u
, "Failed to parse netns socket value: %s", value
);
2952 safe_close((*rt
)->netns_storage_socket
[0]);
2953 (*rt
)->netns_storage_socket
[0] = fdset_remove(fds
, fd
);
2955 } else if (streq(key
, "netns-socket-1")) {
2958 r
= exec_runtime_allocate(rt
);
2962 if (safe_atoi(value
, &fd
) < 0 || !fdset_contains(fds
, fd
))
2963 log_unit_debug(u
, "Failed to parse netns socket value: %s", value
);
2965 safe_close((*rt
)->netns_storage_socket
[1]);
2966 (*rt
)->netns_storage_socket
[1] = fdset_remove(fds
, fd
);
2974 static void *remove_tmpdir_thread(void *p
) {
2975 _cleanup_free_
char *path
= p
;
2977 (void) rm_rf(path
, REMOVE_ROOT
|REMOVE_PHYSICAL
);
2981 void exec_runtime_destroy(ExecRuntime
*rt
) {
2987 /* If there are multiple users of this, let's leave the stuff around */
2992 log_debug("Spawning thread to nuke %s", rt
->tmp_dir
);
2994 r
= asynchronous_job(remove_tmpdir_thread
, rt
->tmp_dir
);
2996 log_warning_errno(r
, "Failed to nuke %s: %m", rt
->tmp_dir
);
3003 if (rt
->var_tmp_dir
) {
3004 log_debug("Spawning thread to nuke %s", rt
->var_tmp_dir
);
3006 r
= asynchronous_job(remove_tmpdir_thread
, rt
->var_tmp_dir
);
3008 log_warning_errno(r
, "Failed to nuke %s: %m", rt
->var_tmp_dir
);
3009 free(rt
->var_tmp_dir
);
3012 rt
->var_tmp_dir
= NULL
;
3015 safe_close_pair(rt
->netns_storage_socket
);
3018 static const char* const exec_input_table
[_EXEC_INPUT_MAX
] = {
3019 [EXEC_INPUT_NULL
] = "null",
3020 [EXEC_INPUT_TTY
] = "tty",
3021 [EXEC_INPUT_TTY_FORCE
] = "tty-force",
3022 [EXEC_INPUT_TTY_FAIL
] = "tty-fail",
3023 [EXEC_INPUT_SOCKET
] = "socket"
3026 DEFINE_STRING_TABLE_LOOKUP(exec_input
, ExecInput
);
3028 static const char* const exec_output_table
[_EXEC_OUTPUT_MAX
] = {
3029 [EXEC_OUTPUT_INHERIT
] = "inherit",
3030 [EXEC_OUTPUT_NULL
] = "null",
3031 [EXEC_OUTPUT_TTY
] = "tty",
3032 [EXEC_OUTPUT_SYSLOG
] = "syslog",
3033 [EXEC_OUTPUT_SYSLOG_AND_CONSOLE
] = "syslog+console",
3034 [EXEC_OUTPUT_KMSG
] = "kmsg",
3035 [EXEC_OUTPUT_KMSG_AND_CONSOLE
] = "kmsg+console",
3036 [EXEC_OUTPUT_JOURNAL
] = "journal",
3037 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE
] = "journal+console",
3038 [EXEC_OUTPUT_SOCKET
] = "socket"
3041 DEFINE_STRING_TABLE_LOOKUP(exec_output
, ExecOutput
);
3043 static const char* const exec_utmp_mode_table
[_EXEC_UTMP_MODE_MAX
] = {
3044 [EXEC_UTMP_INIT
] = "init",
3045 [EXEC_UTMP_LOGIN
] = "login",
3046 [EXEC_UTMP_USER
] = "user",
3049 DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode
, ExecUtmpMode
);