]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/execute.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[thirdparty/systemd.git] / src / core / execute.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <glob.h>
25 #include <grp.h>
26 #include <poll.h>
27 #include <signal.h>
28 #include <string.h>
29 #include <sys/personality.h>
30 #include <sys/prctl.h>
31 #include <sys/socket.h>
32 #include <sys/stat.h>
33 #include <sys/un.h>
34 #include <unistd.h>
35 #include <utmpx.h>
36
37 #ifdef HAVE_PAM
38 #include <security/pam_appl.h>
39 #endif
40
41 #ifdef HAVE_SELINUX
42 #include <selinux/selinux.h>
43 #endif
44
45 #ifdef HAVE_SECCOMP
46 #include <seccomp.h>
47 #endif
48
49 #ifdef HAVE_APPARMOR
50 #include <sys/apparmor.h>
51 #endif
52
53 #include "sd-messages.h"
54
55 #include "af-list.h"
56 #ifdef HAVE_APPARMOR
57 #include "apparmor-util.h"
58 #endif
59 #include "async.h"
60 #include "barrier.h"
61 #include "bus-endpoint.h"
62 #include "cap-list.h"
63 #include "capability.h"
64 #include "def.h"
65 #include "env-util.h"
66 #include "errno-list.h"
67 #include "execute.h"
68 #include "exit-status.h"
69 #include "fd-util.h"
70 #include "fileio.h"
71 #include "formats-util.h"
72 #include "io-util.h"
73 #include "ioprio.h"
74 #include "log.h"
75 #include "macro.h"
76 #include "missing.h"
77 #include "mkdir.h"
78 #include "namespace.h"
79 #include "parse-util.h"
80 #include "path-util.h"
81 #include "process-util.h"
82 #include "rm-rf.h"
83 #ifdef HAVE_SECCOMP
84 #include "seccomp-util.h"
85 #endif
86 #include "securebits.h"
87 #include "selinux-util.h"
88 #include "signal-util.h"
89 #include "smack-util.h"
90 #include "string-util.h"
91 #include "strv.h"
92 #include "terminal-util.h"
93 #include "unit.h"
94 #include "user-util.h"
95 #include "util.h"
96 #include "utmp-wtmp.h"
97
98 #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
99 #define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
100
101 /* This assumes there is a 'tty' group */
102 #define TTY_MODE 0620
103
104 #define SNDBUF_SIZE (8*1024*1024)
105
106 static int shift_fds(int fds[], unsigned n_fds) {
107 int start, restart_from;
108
109 if (n_fds <= 0)
110 return 0;
111
112 /* Modifies the fds array! (sorts it) */
113
114 assert(fds);
115
116 start = 0;
117 for (;;) {
118 int i;
119
120 restart_from = -1;
121
122 for (i = start; i < (int) n_fds; i++) {
123 int nfd;
124
125 /* Already at right index? */
126 if (fds[i] == i+3)
127 continue;
128
129 nfd = fcntl(fds[i], F_DUPFD, i + 3);
130 if (nfd < 0)
131 return -errno;
132
133 safe_close(fds[i]);
134 fds[i] = nfd;
135
136 /* Hmm, the fd we wanted isn't free? Then
137 * let's remember that and try again from here */
138 if (nfd != i+3 && restart_from < 0)
139 restart_from = i;
140 }
141
142 if (restart_from < 0)
143 break;
144
145 start = restart_from;
146 }
147
148 return 0;
149 }
150
151 static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
152 unsigned i;
153 int r;
154
155 if (n_fds <= 0)
156 return 0;
157
158 assert(fds);
159
160 /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
161
162 for (i = 0; i < n_fds; i++) {
163
164 r = fd_nonblock(fds[i], nonblock);
165 if (r < 0)
166 return r;
167
168 /* We unconditionally drop FD_CLOEXEC from the fds,
169 * since after all we want to pass these fds to our
170 * children */
171
172 r = fd_cloexec(fds[i], false);
173 if (r < 0)
174 return r;
175 }
176
177 return 0;
178 }
179
180 _pure_ static const char *tty_path(const ExecContext *context) {
181 assert(context);
182
183 if (context->tty_path)
184 return context->tty_path;
185
186 return "/dev/console";
187 }
188
189 static void exec_context_tty_reset(const ExecContext *context) {
190 assert(context);
191
192 if (context->tty_vhangup)
193 terminal_vhangup(tty_path(context));
194
195 if (context->tty_reset)
196 reset_terminal(tty_path(context));
197
198 if (context->tty_vt_disallocate && context->tty_path)
199 vt_disallocate(context->tty_path);
200 }
201
202 static bool is_terminal_output(ExecOutput o) {
203 return
204 o == EXEC_OUTPUT_TTY ||
205 o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
206 o == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
207 o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE;
208 }
209
210 static int open_null_as(int flags, int nfd) {
211 int fd, r;
212
213 assert(nfd >= 0);
214
215 fd = open("/dev/null", flags|O_NOCTTY);
216 if (fd < 0)
217 return -errno;
218
219 if (fd != nfd) {
220 r = dup2(fd, nfd) < 0 ? -errno : nfd;
221 safe_close(fd);
222 } else
223 r = nfd;
224
225 return r;
226 }
227
228 static int connect_journal_socket(int fd, uid_t uid, gid_t gid) {
229 union sockaddr_union sa = {
230 .un.sun_family = AF_UNIX,
231 .un.sun_path = "/run/systemd/journal/stdout",
232 };
233 uid_t olduid = UID_INVALID;
234 gid_t oldgid = GID_INVALID;
235 int r;
236
237 if (gid != GID_INVALID) {
238 oldgid = getgid();
239
240 r = setegid(gid);
241 if (r < 0)
242 return -errno;
243 }
244
245 if (uid != UID_INVALID) {
246 olduid = getuid();
247
248 r = seteuid(uid);
249 if (r < 0) {
250 r = -errno;
251 goto restore_gid;
252 }
253 }
254
255 r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
256 if (r < 0)
257 r = -errno;
258
259 /* If we fail to restore the uid or gid, things will likely
260 fail later on. This should only happen if an LSM interferes. */
261
262 if (uid != UID_INVALID)
263 (void) seteuid(olduid);
264
265 restore_gid:
266 if (gid != GID_INVALID)
267 (void) setegid(oldgid);
268
269 return r;
270 }
271
272 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) {
273 int fd, r;
274
275 assert(context);
276 assert(output < _EXEC_OUTPUT_MAX);
277 assert(ident);
278 assert(nfd >= 0);
279
280 fd = socket(AF_UNIX, SOCK_STREAM, 0);
281 if (fd < 0)
282 return -errno;
283
284 r = connect_journal_socket(fd, uid, gid);
285 if (r < 0)
286 return r;
287
288 if (shutdown(fd, SHUT_RD) < 0) {
289 safe_close(fd);
290 return -errno;
291 }
292
293 fd_inc_sndbuf(fd, SNDBUF_SIZE);
294
295 dprintf(fd,
296 "%s\n"
297 "%s\n"
298 "%i\n"
299 "%i\n"
300 "%i\n"
301 "%i\n"
302 "%i\n",
303 context->syslog_identifier ? context->syslog_identifier : ident,
304 unit_id,
305 context->syslog_priority,
306 !!context->syslog_level_prefix,
307 output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
308 output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
309 is_terminal_output(output));
310
311 if (fd != nfd) {
312 r = dup2(fd, nfd) < 0 ? -errno : nfd;
313 safe_close(fd);
314 } else
315 r = nfd;
316
317 return r;
318 }
319 static int open_terminal_as(const char *path, mode_t mode, int nfd) {
320 int fd, r;
321
322 assert(path);
323 assert(nfd >= 0);
324
325 fd = open_terminal(path, mode | O_NOCTTY);
326 if (fd < 0)
327 return fd;
328
329 if (fd != nfd) {
330 r = dup2(fd, nfd) < 0 ? -errno : nfd;
331 safe_close(fd);
332 } else
333 r = nfd;
334
335 return r;
336 }
337
338 static bool is_terminal_input(ExecInput i) {
339 return
340 i == EXEC_INPUT_TTY ||
341 i == EXEC_INPUT_TTY_FORCE ||
342 i == EXEC_INPUT_TTY_FAIL;
343 }
344
345 static int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
346
347 if (is_terminal_input(std_input) && !apply_tty_stdin)
348 return EXEC_INPUT_NULL;
349
350 if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
351 return EXEC_INPUT_NULL;
352
353 return std_input;
354 }
355
356 static int fixup_output(ExecOutput std_output, int socket_fd) {
357
358 if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
359 return EXEC_OUTPUT_INHERIT;
360
361 return std_output;
362 }
363
364 static int setup_input(
365 const ExecContext *context,
366 const ExecParameters *params,
367 int socket_fd) {
368
369 ExecInput i;
370
371 assert(context);
372 assert(params);
373
374 if (params->stdin_fd >= 0) {
375 if (dup2(params->stdin_fd, STDIN_FILENO) < 0)
376 return -errno;
377
378 /* Try to make this the controlling tty, if it is a tty, and reset it */
379 (void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE);
380 (void) reset_terminal_fd(STDIN_FILENO, true);
381
382 return STDIN_FILENO;
383 }
384
385 i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin);
386
387 switch (i) {
388
389 case EXEC_INPUT_NULL:
390 return open_null_as(O_RDONLY, STDIN_FILENO);
391
392 case EXEC_INPUT_TTY:
393 case EXEC_INPUT_TTY_FORCE:
394 case EXEC_INPUT_TTY_FAIL: {
395 int fd, r;
396
397 fd = acquire_terminal(tty_path(context),
398 i == EXEC_INPUT_TTY_FAIL,
399 i == EXEC_INPUT_TTY_FORCE,
400 false,
401 USEC_INFINITY);
402 if (fd < 0)
403 return fd;
404
405 if (fd != STDIN_FILENO) {
406 r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
407 safe_close(fd);
408 } else
409 r = STDIN_FILENO;
410
411 return r;
412 }
413
414 case EXEC_INPUT_SOCKET:
415 return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
416
417 default:
418 assert_not_reached("Unknown input type");
419 }
420 }
421
422 static int setup_output(
423 Unit *unit,
424 const ExecContext *context,
425 const ExecParameters *params,
426 int fileno,
427 int socket_fd,
428 const char *ident,
429 uid_t uid, gid_t gid) {
430
431 ExecOutput o;
432 ExecInput i;
433 int r;
434
435 assert(unit);
436 assert(context);
437 assert(params);
438 assert(ident);
439
440 if (fileno == STDOUT_FILENO && params->stdout_fd >= 0) {
441
442 if (dup2(params->stdout_fd, STDOUT_FILENO) < 0)
443 return -errno;
444
445 return STDOUT_FILENO;
446 }
447
448 if (fileno == STDERR_FILENO && params->stderr_fd >= 0) {
449 if (dup2(params->stderr_fd, STDERR_FILENO) < 0)
450 return -errno;
451
452 return STDERR_FILENO;
453 }
454
455 i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin);
456 o = fixup_output(context->std_output, socket_fd);
457
458 if (fileno == STDERR_FILENO) {
459 ExecOutput e;
460 e = fixup_output(context->std_error, socket_fd);
461
462 /* This expects the input and output are already set up */
463
464 /* Don't change the stderr file descriptor if we inherit all
465 * the way and are not on a tty */
466 if (e == EXEC_OUTPUT_INHERIT &&
467 o == EXEC_OUTPUT_INHERIT &&
468 i == EXEC_INPUT_NULL &&
469 !is_terminal_input(context->std_input) &&
470 getppid () != 1)
471 return fileno;
472
473 /* Duplicate from stdout if possible */
474 if (e == o || e == EXEC_OUTPUT_INHERIT)
475 return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
476
477 o = e;
478
479 } else if (o == EXEC_OUTPUT_INHERIT) {
480 /* If input got downgraded, inherit the original value */
481 if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
482 return open_terminal_as(tty_path(context), O_WRONLY, fileno);
483
484 /* If the input is connected to anything that's not a /dev/null, inherit that... */
485 if (i != EXEC_INPUT_NULL)
486 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
487
488 /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
489 if (getppid() != 1)
490 return fileno;
491
492 /* We need to open /dev/null here anew, to get the right access mode. */
493 return open_null_as(O_WRONLY, fileno);
494 }
495
496 switch (o) {
497
498 case EXEC_OUTPUT_NULL:
499 return open_null_as(O_WRONLY, fileno);
500
501 case EXEC_OUTPUT_TTY:
502 if (is_terminal_input(i))
503 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
504
505 /* We don't reset the terminal if this is just about output */
506 return open_terminal_as(tty_path(context), O_WRONLY, fileno);
507
508 case EXEC_OUTPUT_SYSLOG:
509 case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
510 case EXEC_OUTPUT_KMSG:
511 case EXEC_OUTPUT_KMSG_AND_CONSOLE:
512 case EXEC_OUTPUT_JOURNAL:
513 case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
514 r = connect_logger_as(context, o, ident, unit->id, fileno, uid, gid);
515 if (r < 0) {
516 log_unit_error_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr");
517 r = open_null_as(O_WRONLY, fileno);
518 }
519 return r;
520
521 case EXEC_OUTPUT_SOCKET:
522 assert(socket_fd >= 0);
523 return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
524
525 default:
526 assert_not_reached("Unknown error type");
527 }
528 }
529
530 static int chown_terminal(int fd, uid_t uid) {
531 struct stat st;
532
533 assert(fd >= 0);
534
535 /* This might fail. What matters are the results. */
536 (void) fchown(fd, uid, -1);
537 (void) fchmod(fd, TTY_MODE);
538
539 if (fstat(fd, &st) < 0)
540 return -errno;
541
542 if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
543 return -EPERM;
544
545 return 0;
546 }
547
548 static int setup_confirm_stdio(int *_saved_stdin, int *_saved_stdout) {
549 _cleanup_close_ int fd = -1, saved_stdin = -1, saved_stdout = -1;
550 int r;
551
552 assert(_saved_stdin);
553 assert(_saved_stdout);
554
555 saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
556 if (saved_stdin < 0)
557 return -errno;
558
559 saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
560 if (saved_stdout < 0)
561 return -errno;
562
563 fd = acquire_terminal(
564 "/dev/console",
565 false,
566 false,
567 false,
568 DEFAULT_CONFIRM_USEC);
569 if (fd < 0)
570 return fd;
571
572 r = chown_terminal(fd, getuid());
573 if (r < 0)
574 return r;
575
576 r = reset_terminal_fd(fd, true);
577 if (r < 0)
578 return r;
579
580 if (dup2(fd, STDIN_FILENO) < 0)
581 return -errno;
582
583 if (dup2(fd, STDOUT_FILENO) < 0)
584 return -errno;
585
586 if (fd >= 2)
587 safe_close(fd);
588 fd = -1;
589
590 *_saved_stdin = saved_stdin;
591 *_saved_stdout = saved_stdout;
592
593 saved_stdin = saved_stdout = -1;
594
595 return 0;
596 }
597
598 _printf_(1, 2) static int write_confirm_message(const char *format, ...) {
599 _cleanup_close_ int fd = -1;
600 va_list ap;
601
602 assert(format);
603
604 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
605 if (fd < 0)
606 return fd;
607
608 va_start(ap, format);
609 vdprintf(fd, format, ap);
610 va_end(ap);
611
612 return 0;
613 }
614
615 static int restore_confirm_stdio(int *saved_stdin, int *saved_stdout) {
616 int r = 0;
617
618 assert(saved_stdin);
619 assert(saved_stdout);
620
621 release_terminal();
622
623 if (*saved_stdin >= 0)
624 if (dup2(*saved_stdin, STDIN_FILENO) < 0)
625 r = -errno;
626
627 if (*saved_stdout >= 0)
628 if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
629 r = -errno;
630
631 *saved_stdin = safe_close(*saved_stdin);
632 *saved_stdout = safe_close(*saved_stdout);
633
634 return r;
635 }
636
637 static int ask_for_confirmation(char *response, char **argv) {
638 int saved_stdout = -1, saved_stdin = -1, r;
639 _cleanup_free_ char *line = NULL;
640
641 r = setup_confirm_stdio(&saved_stdin, &saved_stdout);
642 if (r < 0)
643 return r;
644
645 line = exec_command_line(argv);
646 if (!line)
647 return -ENOMEM;
648
649 r = ask_char(response, "yns", "Execute %s? [Yes, No, Skip] ", line);
650
651 restore_confirm_stdio(&saved_stdin, &saved_stdout);
652
653 return r;
654 }
655
656 static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
657 bool keep_groups = false;
658 int r;
659
660 assert(context);
661
662 /* Lookup and set GID and supplementary group list. Here too
663 * we avoid NSS lookups for gid=0. */
664
665 if (context->group || username) {
666 /* First step, initialize groups from /etc/groups */
667 if (username && gid != 0) {
668 if (initgroups(username, gid) < 0)
669 return -errno;
670
671 keep_groups = true;
672 }
673
674 /* Second step, set our gids */
675 if (setresgid(gid, gid, gid) < 0)
676 return -errno;
677 }
678
679 if (context->supplementary_groups) {
680 int ngroups_max, k;
681 gid_t *gids;
682 char **i;
683
684 /* Final step, initialize any manually set supplementary groups */
685 assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
686
687 if (!(gids = new(gid_t, ngroups_max)))
688 return -ENOMEM;
689
690 if (keep_groups) {
691 k = getgroups(ngroups_max, gids);
692 if (k < 0) {
693 free(gids);
694 return -errno;
695 }
696 } else
697 k = 0;
698
699 STRV_FOREACH(i, context->supplementary_groups) {
700 const char *g;
701
702 if (k >= ngroups_max) {
703 free(gids);
704 return -E2BIG;
705 }
706
707 g = *i;
708 r = get_group_creds(&g, gids+k);
709 if (r < 0) {
710 free(gids);
711 return r;
712 }
713
714 k++;
715 }
716
717 if (setgroups(k, gids) < 0) {
718 free(gids);
719 return -errno;
720 }
721
722 free(gids);
723 }
724
725 return 0;
726 }
727
728 static int enforce_user(const ExecContext *context, uid_t uid) {
729 assert(context);
730
731 /* Sets (but doesn't lookup) the uid and make sure we keep the
732 * capabilities while doing so. */
733
734 if (context->capabilities) {
735 _cleanup_cap_free_ cap_t d = NULL;
736 static const cap_value_t bits[] = {
737 CAP_SETUID, /* Necessary so that we can run setresuid() below */
738 CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
739 };
740
741 /* First step: If we need to keep capabilities but
742 * drop privileges we need to make sure we keep our
743 * caps, while we drop privileges. */
744 if (uid != 0) {
745 int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
746
747 if (prctl(PR_GET_SECUREBITS) != sb)
748 if (prctl(PR_SET_SECUREBITS, sb) < 0)
749 return -errno;
750 }
751
752 /* Second step: set the capabilities. This will reduce
753 * the capabilities to the minimum we need. */
754
755 d = cap_dup(context->capabilities);
756 if (!d)
757 return -errno;
758
759 if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
760 cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0)
761 return -errno;
762
763 if (cap_set_proc(d) < 0)
764 return -errno;
765 }
766
767 /* Third step: actually set the uids */
768 if (setresuid(uid, uid, uid) < 0)
769 return -errno;
770
771 /* At this point we should have all necessary capabilities but
772 are otherwise a normal user. However, the caps might got
773 corrupted due to the setresuid() so we need clean them up
774 later. This is done outside of this call. */
775
776 return 0;
777 }
778
779 #ifdef HAVE_PAM
780
781 static int null_conv(
782 int num_msg,
783 const struct pam_message **msg,
784 struct pam_response **resp,
785 void *appdata_ptr) {
786
787 /* We don't support conversations */
788
789 return PAM_CONV_ERR;
790 }
791
792 static int setup_pam(
793 const char *name,
794 const char *user,
795 uid_t uid,
796 const char *tty,
797 char ***pam_env,
798 int fds[], unsigned n_fds) {
799
800 static const struct pam_conv conv = {
801 .conv = null_conv,
802 .appdata_ptr = NULL
803 };
804
805 _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
806 pam_handle_t *handle = NULL;
807 sigset_t old_ss;
808 int pam_code = PAM_SUCCESS;
809 int err = 0;
810 char **e = NULL;
811 bool close_session = false;
812 pid_t pam_pid = 0, parent_pid;
813 int flags = 0;
814
815 assert(name);
816 assert(user);
817 assert(pam_env);
818
819 /* We set up PAM in the parent process, then fork. The child
820 * will then stay around until killed via PR_GET_PDEATHSIG or
821 * systemd via the cgroup logic. It will then remove the PAM
822 * session again. The parent process will exec() the actual
823 * daemon. We do things this way to ensure that the main PID
824 * of the daemon is the one we initially fork()ed. */
825
826 err = barrier_create(&barrier);
827 if (err < 0)
828 goto fail;
829
830 if (log_get_max_level() < LOG_DEBUG)
831 flags |= PAM_SILENT;
832
833 pam_code = pam_start(name, user, &conv, &handle);
834 if (pam_code != PAM_SUCCESS) {
835 handle = NULL;
836 goto fail;
837 }
838
839 if (tty) {
840 pam_code = pam_set_item(handle, PAM_TTY, tty);
841 if (pam_code != PAM_SUCCESS)
842 goto fail;
843 }
844
845 pam_code = pam_acct_mgmt(handle, flags);
846 if (pam_code != PAM_SUCCESS)
847 goto fail;
848
849 pam_code = pam_open_session(handle, flags);
850 if (pam_code != PAM_SUCCESS)
851 goto fail;
852
853 close_session = true;
854
855 e = pam_getenvlist(handle);
856 if (!e) {
857 pam_code = PAM_BUF_ERR;
858 goto fail;
859 }
860
861 /* Block SIGTERM, so that we know that it won't get lost in
862 * the child */
863
864 assert_se(sigprocmask_many(SIG_BLOCK, &old_ss, SIGTERM, -1) >= 0);
865
866 parent_pid = getpid();
867
868 pam_pid = fork();
869 if (pam_pid < 0)
870 goto fail;
871
872 if (pam_pid == 0) {
873 int sig;
874 int r = EXIT_PAM;
875
876 /* The child's job is to reset the PAM session on
877 * termination */
878 barrier_set_role(&barrier, BARRIER_CHILD);
879
880 /* This string must fit in 10 chars (i.e. the length
881 * of "/sbin/init"), to look pretty in /bin/ps */
882 rename_process("(sd-pam)");
883
884 /* Make sure we don't keep open the passed fds in this
885 child. We assume that otherwise only those fds are
886 open here that have been opened by PAM. */
887 close_many(fds, n_fds);
888
889 /* Drop privileges - we don't need any to pam_close_session
890 * and this will make PR_SET_PDEATHSIG work in most cases.
891 * If this fails, ignore the error - but expect sd-pam threads
892 * to fail to exit normally */
893 if (setresuid(uid, uid, uid) < 0)
894 log_error_errno(r, "Error: Failed to setresuid() in sd-pam: %m");
895
896 (void) ignore_signals(SIGPIPE, -1);
897
898 /* Wait until our parent died. This will only work if
899 * the above setresuid() succeeds, otherwise the kernel
900 * will not allow unprivileged parents kill their privileged
901 * children this way. We rely on the control groups kill logic
902 * to do the rest for us. */
903 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
904 goto child_finish;
905
906 /* Tell the parent that our setup is done. This is especially
907 * important regarding dropping privileges. Otherwise, unit
908 * setup might race against our setresuid(2) call. */
909 barrier_place(&barrier);
910
911 /* Check if our parent process might already have
912 * died? */
913 if (getppid() == parent_pid) {
914 sigset_t ss;
915
916 assert_se(sigemptyset(&ss) >= 0);
917 assert_se(sigaddset(&ss, SIGTERM) >= 0);
918
919 for (;;) {
920 if (sigwait(&ss, &sig) < 0) {
921 if (errno == EINTR)
922 continue;
923
924 goto child_finish;
925 }
926
927 assert(sig == SIGTERM);
928 break;
929 }
930 }
931
932 /* If our parent died we'll end the session */
933 if (getppid() != parent_pid) {
934 pam_code = pam_close_session(handle, flags);
935 if (pam_code != PAM_SUCCESS)
936 goto child_finish;
937 }
938
939 r = 0;
940
941 child_finish:
942 pam_end(handle, pam_code | flags);
943 _exit(r);
944 }
945
946 barrier_set_role(&barrier, BARRIER_PARENT);
947
948 /* If the child was forked off successfully it will do all the
949 * cleanups, so forget about the handle here. */
950 handle = NULL;
951
952 /* Unblock SIGTERM again in the parent */
953 assert_se(sigprocmask(SIG_SETMASK, &old_ss, NULL) >= 0);
954
955 /* We close the log explicitly here, since the PAM modules
956 * might have opened it, but we don't want this fd around. */
957 closelog();
958
959 /* Synchronously wait for the child to initialize. We don't care for
960 * errors as we cannot recover. However, warn loudly if it happens. */
961 if (!barrier_place_and_sync(&barrier))
962 log_error("PAM initialization failed");
963
964 *pam_env = e;
965 e = NULL;
966
967 return 0;
968
969 fail:
970 if (pam_code != PAM_SUCCESS) {
971 log_error("PAM failed: %s", pam_strerror(handle, pam_code));
972 err = -EPERM; /* PAM errors do not map to errno */
973 } else {
974 err = log_error_errno(err < 0 ? err : errno, "PAM failed: %m");
975 }
976
977 if (handle) {
978 if (close_session)
979 pam_code = pam_close_session(handle, flags);
980
981 pam_end(handle, pam_code | flags);
982 }
983
984 strv_free(e);
985
986 closelog();
987
988 if (pam_pid > 1) {
989 kill(pam_pid, SIGTERM);
990 kill(pam_pid, SIGCONT);
991 }
992
993 return err;
994 }
995 #endif
996
997 static void rename_process_from_path(const char *path) {
998 char process_name[11];
999 const char *p;
1000 size_t l;
1001
1002 /* This resulting string must fit in 10 chars (i.e. the length
1003 * of "/sbin/init") to look pretty in /bin/ps */
1004
1005 p = basename(path);
1006 if (isempty(p)) {
1007 rename_process("(...)");
1008 return;
1009 }
1010
1011 l = strlen(p);
1012 if (l > 8) {
1013 /* The end of the process name is usually more
1014 * interesting, since the first bit might just be
1015 * "systemd-" */
1016 p = p + l - 8;
1017 l = 8;
1018 }
1019
1020 process_name[0] = '(';
1021 memcpy(process_name+1, p, l);
1022 process_name[1+l] = ')';
1023 process_name[1+l+1] = 0;
1024
1025 rename_process(process_name);
1026 }
1027
1028 #ifdef HAVE_SECCOMP
1029
1030 static int apply_seccomp(const ExecContext *c) {
1031 uint32_t negative_action, action;
1032 scmp_filter_ctx *seccomp;
1033 Iterator i;
1034 void *id;
1035 int r;
1036
1037 assert(c);
1038
1039 negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno);
1040
1041 seccomp = seccomp_init(c->syscall_whitelist ? negative_action : SCMP_ACT_ALLOW);
1042 if (!seccomp)
1043 return -ENOMEM;
1044
1045 if (c->syscall_archs) {
1046
1047 SET_FOREACH(id, c->syscall_archs, i) {
1048 r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
1049 if (r == -EEXIST)
1050 continue;
1051 if (r < 0)
1052 goto finish;
1053 }
1054
1055 } else {
1056 r = seccomp_add_secondary_archs(seccomp);
1057 if (r < 0)
1058 goto finish;
1059 }
1060
1061 action = c->syscall_whitelist ? SCMP_ACT_ALLOW : negative_action;
1062 SET_FOREACH(id, c->syscall_filter, i) {
1063 r = seccomp_rule_add(seccomp, action, PTR_TO_INT(id) - 1, 0);
1064 if (r < 0)
1065 goto finish;
1066 }
1067
1068 r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
1069 if (r < 0)
1070 goto finish;
1071
1072 r = seccomp_load(seccomp);
1073
1074 finish:
1075 seccomp_release(seccomp);
1076 return r;
1077 }
1078
1079 static int apply_address_families(const ExecContext *c) {
1080 scmp_filter_ctx *seccomp;
1081 Iterator i;
1082 int r;
1083
1084 assert(c);
1085
1086 seccomp = seccomp_init(SCMP_ACT_ALLOW);
1087 if (!seccomp)
1088 return -ENOMEM;
1089
1090 r = seccomp_add_secondary_archs(seccomp);
1091 if (r < 0)
1092 goto finish;
1093
1094 if (c->address_families_whitelist) {
1095 int af, first = 0, last = 0;
1096 void *afp;
1097
1098 /* If this is a whitelist, we first block the address
1099 * families that are out of range and then everything
1100 * that is not in the set. First, we find the lowest
1101 * and highest address family in the set. */
1102
1103 SET_FOREACH(afp, c->address_families, i) {
1104 af = PTR_TO_INT(afp);
1105
1106 if (af <= 0 || af >= af_max())
1107 continue;
1108
1109 if (first == 0 || af < first)
1110 first = af;
1111
1112 if (last == 0 || af > last)
1113 last = af;
1114 }
1115
1116 assert((first == 0) == (last == 0));
1117
1118 if (first == 0) {
1119
1120 /* No entries in the valid range, block everything */
1121 r = seccomp_rule_add(
1122 seccomp,
1123 SCMP_ACT_ERRNO(EPROTONOSUPPORT),
1124 SCMP_SYS(socket),
1125 0);
1126 if (r < 0)
1127 goto finish;
1128
1129 } else {
1130
1131 /* Block everything below the first entry */
1132 r = seccomp_rule_add(
1133 seccomp,
1134 SCMP_ACT_ERRNO(EPROTONOSUPPORT),
1135 SCMP_SYS(socket),
1136 1,
1137 SCMP_A0(SCMP_CMP_LT, first));
1138 if (r < 0)
1139 goto finish;
1140
1141 /* Block everything above the last entry */
1142 r = seccomp_rule_add(
1143 seccomp,
1144 SCMP_ACT_ERRNO(EPROTONOSUPPORT),
1145 SCMP_SYS(socket),
1146 1,
1147 SCMP_A0(SCMP_CMP_GT, last));
1148 if (r < 0)
1149 goto finish;
1150
1151 /* Block everything between the first and last
1152 * entry */
1153 for (af = 1; af < af_max(); af++) {
1154
1155 if (set_contains(c->address_families, INT_TO_PTR(af)))
1156 continue;
1157
1158 r = seccomp_rule_add(
1159 seccomp,
1160 SCMP_ACT_ERRNO(EPROTONOSUPPORT),
1161 SCMP_SYS(socket),
1162 1,
1163 SCMP_A0(SCMP_CMP_EQ, af));
1164 if (r < 0)
1165 goto finish;
1166 }
1167 }
1168
1169 } else {
1170 void *af;
1171
1172 /* If this is a blacklist, then generate one rule for
1173 * each address family that are then combined in OR
1174 * checks. */
1175
1176 SET_FOREACH(af, c->address_families, i) {
1177
1178 r = seccomp_rule_add(
1179 seccomp,
1180 SCMP_ACT_ERRNO(EPROTONOSUPPORT),
1181 SCMP_SYS(socket),
1182 1,
1183 SCMP_A0(SCMP_CMP_EQ, PTR_TO_INT(af)));
1184 if (r < 0)
1185 goto finish;
1186 }
1187 }
1188
1189 r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
1190 if (r < 0)
1191 goto finish;
1192
1193 r = seccomp_load(seccomp);
1194
1195 finish:
1196 seccomp_release(seccomp);
1197 return r;
1198 }
1199
1200 #endif
1201
1202 static void do_idle_pipe_dance(int idle_pipe[4]) {
1203 assert(idle_pipe);
1204
1205
1206 idle_pipe[1] = safe_close(idle_pipe[1]);
1207 idle_pipe[2] = safe_close(idle_pipe[2]);
1208
1209 if (idle_pipe[0] >= 0) {
1210 int r;
1211
1212 r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
1213
1214 if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
1215 ssize_t n;
1216
1217 /* Signal systemd that we are bored and want to continue. */
1218 n = write(idle_pipe[3], "x", 1);
1219 if (n > 0)
1220 /* Wait for systemd to react to the signal above. */
1221 fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
1222 }
1223
1224 idle_pipe[0] = safe_close(idle_pipe[0]);
1225
1226 }
1227
1228 idle_pipe[3] = safe_close(idle_pipe[3]);
1229 }
1230
1231 static int build_environment(
1232 const ExecContext *c,
1233 unsigned n_fds,
1234 char ** fd_names,
1235 usec_t watchdog_usec,
1236 const char *home,
1237 const char *username,
1238 const char *shell,
1239 char ***ret) {
1240
1241 _cleanup_strv_free_ char **our_env = NULL;
1242 unsigned n_env = 0;
1243 char *x;
1244
1245 assert(c);
1246 assert(ret);
1247
1248 our_env = new0(char*, 11);
1249 if (!our_env)
1250 return -ENOMEM;
1251
1252 if (n_fds > 0) {
1253 _cleanup_free_ char *joined = NULL;
1254
1255 if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid()) < 0)
1256 return -ENOMEM;
1257 our_env[n_env++] = x;
1258
1259 if (asprintf(&x, "LISTEN_FDS=%u", n_fds) < 0)
1260 return -ENOMEM;
1261 our_env[n_env++] = x;
1262
1263 joined = strv_join(fd_names, ":");
1264 if (!joined)
1265 return -ENOMEM;
1266
1267 x = strjoin("LISTEN_FDNAMES=", joined, NULL);
1268 if (!x)
1269 return -ENOMEM;
1270 our_env[n_env++] = x;
1271 }
1272
1273 if (watchdog_usec > 0) {
1274 if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid()) < 0)
1275 return -ENOMEM;
1276 our_env[n_env++] = x;
1277
1278 if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, watchdog_usec) < 0)
1279 return -ENOMEM;
1280 our_env[n_env++] = x;
1281 }
1282
1283 if (home) {
1284 x = strappend("HOME=", home);
1285 if (!x)
1286 return -ENOMEM;
1287 our_env[n_env++] = x;
1288 }
1289
1290 if (username) {
1291 x = strappend("LOGNAME=", username);
1292 if (!x)
1293 return -ENOMEM;
1294 our_env[n_env++] = x;
1295
1296 x = strappend("USER=", username);
1297 if (!x)
1298 return -ENOMEM;
1299 our_env[n_env++] = x;
1300 }
1301
1302 if (shell) {
1303 x = strappend("SHELL=", shell);
1304 if (!x)
1305 return -ENOMEM;
1306 our_env[n_env++] = x;
1307 }
1308
1309 if (is_terminal_input(c->std_input) ||
1310 c->std_output == EXEC_OUTPUT_TTY ||
1311 c->std_error == EXEC_OUTPUT_TTY ||
1312 c->tty_path) {
1313
1314 x = strdup(default_term_for_tty(tty_path(c)));
1315 if (!x)
1316 return -ENOMEM;
1317 our_env[n_env++] = x;
1318 }
1319
1320 our_env[n_env++] = NULL;
1321 assert(n_env <= 11);
1322
1323 *ret = our_env;
1324 our_env = NULL;
1325
1326 return 0;
1327 }
1328
1329 static bool exec_needs_mount_namespace(
1330 const ExecContext *context,
1331 const ExecParameters *params,
1332 ExecRuntime *runtime) {
1333
1334 assert(context);
1335 assert(params);
1336
1337 if (!strv_isempty(context->read_write_dirs) ||
1338 !strv_isempty(context->read_only_dirs) ||
1339 !strv_isempty(context->inaccessible_dirs))
1340 return true;
1341
1342 if (context->mount_flags != 0)
1343 return true;
1344
1345 if (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir))
1346 return true;
1347
1348 if (params->bus_endpoint_path)
1349 return true;
1350
1351 if (context->private_devices ||
1352 context->protect_system != PROTECT_SYSTEM_NO ||
1353 context->protect_home != PROTECT_HOME_NO)
1354 return true;
1355
1356 return false;
1357 }
1358
1359 static int close_remaining_fds(
1360 const ExecParameters *params,
1361 ExecRuntime *runtime,
1362 int socket_fd,
1363 int *fds, unsigned n_fds) {
1364
1365 unsigned n_dont_close = 0;
1366 int dont_close[n_fds + 7];
1367
1368 assert(params);
1369
1370 if (params->stdin_fd >= 0)
1371 dont_close[n_dont_close++] = params->stdin_fd;
1372 if (params->stdout_fd >= 0)
1373 dont_close[n_dont_close++] = params->stdout_fd;
1374 if (params->stderr_fd >= 0)
1375 dont_close[n_dont_close++] = params->stderr_fd;
1376
1377 if (socket_fd >= 0)
1378 dont_close[n_dont_close++] = socket_fd;
1379 if (n_fds > 0) {
1380 memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
1381 n_dont_close += n_fds;
1382 }
1383
1384 if (params->bus_endpoint_fd >= 0)
1385 dont_close[n_dont_close++] = params->bus_endpoint_fd;
1386
1387 if (runtime) {
1388 if (runtime->netns_storage_socket[0] >= 0)
1389 dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
1390 if (runtime->netns_storage_socket[1] >= 0)
1391 dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
1392 }
1393
1394 return close_all_fds(dont_close, n_dont_close);
1395 }
1396
1397 static int exec_child(
1398 Unit *unit,
1399 ExecCommand *command,
1400 const ExecContext *context,
1401 const ExecParameters *params,
1402 ExecRuntime *runtime,
1403 char **argv,
1404 int socket_fd,
1405 int *fds, unsigned n_fds,
1406 char **files_env,
1407 int *exit_status) {
1408
1409 _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
1410 _cleanup_free_ char *mac_selinux_context_net = NULL;
1411 const char *username = NULL, *home = NULL, *shell = NULL, *wd;
1412 uid_t uid = UID_INVALID;
1413 gid_t gid = GID_INVALID;
1414 int i, r;
1415 bool needs_mount_namespace;
1416
1417 assert(unit);
1418 assert(command);
1419 assert(context);
1420 assert(params);
1421 assert(exit_status);
1422
1423 rename_process_from_path(command->path);
1424
1425 /* We reset exactly these signals, since they are the
1426 * only ones we set to SIG_IGN in the main daemon. All
1427 * others we leave untouched because we set them to
1428 * SIG_DFL or a valid handler initially, both of which
1429 * will be demoted to SIG_DFL. */
1430 (void) default_signals(SIGNALS_CRASH_HANDLER,
1431 SIGNALS_IGNORE, -1);
1432
1433 if (context->ignore_sigpipe)
1434 (void) ignore_signals(SIGPIPE, -1);
1435
1436 r = reset_signal_mask();
1437 if (r < 0) {
1438 *exit_status = EXIT_SIGNAL_MASK;
1439 return r;
1440 }
1441
1442 if (params->idle_pipe)
1443 do_idle_pipe_dance(params->idle_pipe);
1444
1445 /* Close sockets very early to make sure we don't
1446 * block init reexecution because it cannot bind its
1447 * sockets */
1448
1449 log_forget_fds();
1450
1451 r = close_remaining_fds(params, runtime, socket_fd, fds, n_fds);
1452 if (r < 0) {
1453 *exit_status = EXIT_FDS;
1454 return r;
1455 }
1456
1457 if (!context->same_pgrp)
1458 if (setsid() < 0) {
1459 *exit_status = EXIT_SETSID;
1460 return -errno;
1461 }
1462
1463 exec_context_tty_reset(context);
1464
1465 if (params->confirm_spawn) {
1466 char response;
1467
1468 r = ask_for_confirmation(&response, argv);
1469 if (r == -ETIMEDOUT)
1470 write_confirm_message("Confirmation question timed out, assuming positive response.\n");
1471 else if (r < 0)
1472 write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-r));
1473 else if (response == 's') {
1474 write_confirm_message("Skipping execution.\n");
1475 *exit_status = EXIT_CONFIRM;
1476 return -ECANCELED;
1477 } else if (response == 'n') {
1478 write_confirm_message("Failing execution.\n");
1479 *exit_status = 0;
1480 return 0;
1481 }
1482 }
1483
1484 if (context->user) {
1485 username = context->user;
1486 r = get_user_creds(&username, &uid, &gid, &home, &shell);
1487 if (r < 0) {
1488 *exit_status = EXIT_USER;
1489 return r;
1490 }
1491 }
1492
1493 if (context->group) {
1494 const char *g = context->group;
1495
1496 r = get_group_creds(&g, &gid);
1497 if (r < 0) {
1498 *exit_status = EXIT_GROUP;
1499 return r;
1500 }
1501 }
1502
1503
1504 /* If a socket is connected to STDIN/STDOUT/STDERR, we
1505 * must sure to drop O_NONBLOCK */
1506 if (socket_fd >= 0)
1507 (void) fd_nonblock(socket_fd, false);
1508
1509 r = setup_input(context, params, socket_fd);
1510 if (r < 0) {
1511 *exit_status = EXIT_STDIN;
1512 return r;
1513 }
1514
1515 r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid);
1516 if (r < 0) {
1517 *exit_status = EXIT_STDOUT;
1518 return r;
1519 }
1520
1521 r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid);
1522 if (r < 0) {
1523 *exit_status = EXIT_STDERR;
1524 return r;
1525 }
1526
1527 if (params->cgroup_path) {
1528 r = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0, NULL, NULL);
1529 if (r < 0) {
1530 *exit_status = EXIT_CGROUP;
1531 return r;
1532 }
1533 }
1534
1535 if (context->oom_score_adjust_set) {
1536 char t[DECIMAL_STR_MAX(context->oom_score_adjust)];
1537
1538 /* When we can't make this change due to EPERM, then
1539 * let's silently skip over it. User namespaces
1540 * prohibit write access to this file, and we
1541 * shouldn't trip up over that. */
1542
1543 sprintf(t, "%i", context->oom_score_adjust);
1544 r = write_string_file("/proc/self/oom_score_adj", t, 0);
1545 if (r == -EPERM || r == -EACCES) {
1546 log_open();
1547 log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
1548 log_close();
1549 } else if (r < 0) {
1550 *exit_status = EXIT_OOM_ADJUST;
1551 return -errno;
1552 }
1553 }
1554
1555 if (context->nice_set)
1556 if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
1557 *exit_status = EXIT_NICE;
1558 return -errno;
1559 }
1560
1561 if (context->cpu_sched_set) {
1562 struct sched_param param = {
1563 .sched_priority = context->cpu_sched_priority,
1564 };
1565
1566 r = sched_setscheduler(0,
1567 context->cpu_sched_policy |
1568 (context->cpu_sched_reset_on_fork ?
1569 SCHED_RESET_ON_FORK : 0),
1570 &param);
1571 if (r < 0) {
1572 *exit_status = EXIT_SETSCHEDULER;
1573 return -errno;
1574 }
1575 }
1576
1577 if (context->cpuset)
1578 if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
1579 *exit_status = EXIT_CPUAFFINITY;
1580 return -errno;
1581 }
1582
1583 if (context->ioprio_set)
1584 if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
1585 *exit_status = EXIT_IOPRIO;
1586 return -errno;
1587 }
1588
1589 if (context->timer_slack_nsec != NSEC_INFINITY)
1590 if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
1591 *exit_status = EXIT_TIMERSLACK;
1592 return -errno;
1593 }
1594
1595 if (context->personality != PERSONALITY_INVALID)
1596 if (personality(context->personality) < 0) {
1597 *exit_status = EXIT_PERSONALITY;
1598 return -errno;
1599 }
1600
1601 if (context->utmp_id)
1602 utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path,
1603 context->utmp_mode == EXEC_UTMP_INIT ? INIT_PROCESS :
1604 context->utmp_mode == EXEC_UTMP_LOGIN ? LOGIN_PROCESS :
1605 USER_PROCESS,
1606 username ? "root" : context->user);
1607
1608 if (context->user && is_terminal_input(context->std_input)) {
1609 r = chown_terminal(STDIN_FILENO, uid);
1610 if (r < 0) {
1611 *exit_status = EXIT_STDIN;
1612 return r;
1613 }
1614 }
1615
1616 if (params->bus_endpoint_fd >= 0 && context->bus_endpoint) {
1617 uid_t ep_uid = (uid == UID_INVALID) ? 0 : uid;
1618
1619 r = bus_kernel_set_endpoint_policy(params->bus_endpoint_fd, ep_uid, context->bus_endpoint);
1620 if (r < 0) {
1621 *exit_status = EXIT_BUS_ENDPOINT;
1622 return r;
1623 }
1624 }
1625
1626 /* If delegation is enabled we'll pass ownership of the cgroup
1627 * (but only in systemd's own controller hierarchy!) to the
1628 * user of the new process. */
1629 if (params->cgroup_path && context->user && params->cgroup_delegate) {
1630 r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0644, uid, gid);
1631 if (r < 0) {
1632 *exit_status = EXIT_CGROUP;
1633 return r;
1634 }
1635
1636
1637 r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0755, uid, gid);
1638 if (r < 0) {
1639 *exit_status = EXIT_CGROUP;
1640 return r;
1641 }
1642 }
1643
1644 if (!strv_isempty(context->runtime_directory) && params->runtime_prefix) {
1645 char **rt;
1646
1647 STRV_FOREACH(rt, context->runtime_directory) {
1648 _cleanup_free_ char *p;
1649
1650 p = strjoin(params->runtime_prefix, "/", *rt, NULL);
1651 if (!p) {
1652 *exit_status = EXIT_RUNTIME_DIRECTORY;
1653 return -ENOMEM;
1654 }
1655
1656 r = mkdir_p_label(p, context->runtime_directory_mode);
1657 if (r < 0) {
1658 *exit_status = EXIT_RUNTIME_DIRECTORY;
1659 return r;
1660 }
1661
1662 r = chmod_and_chown(p, context->runtime_directory_mode, uid, gid);
1663 if (r < 0) {
1664 *exit_status = EXIT_RUNTIME_DIRECTORY;
1665 return r;
1666 }
1667 }
1668 }
1669
1670 umask(context->umask);
1671
1672 if (params->apply_permissions) {
1673 r = enforce_groups(context, username, gid);
1674 if (r < 0) {
1675 *exit_status = EXIT_GROUP;
1676 return r;
1677 }
1678 #ifdef HAVE_SMACK
1679 if (context->smack_process_label) {
1680 r = mac_smack_apply_pid(0, context->smack_process_label);
1681 if (r < 0) {
1682 *exit_status = EXIT_SMACK_PROCESS_LABEL;
1683 return r;
1684 }
1685 }
1686 #ifdef SMACK_DEFAULT_PROCESS_LABEL
1687 else {
1688 _cleanup_free_ char *exec_label = NULL;
1689
1690 r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label);
1691 if (r < 0 && r != -ENODATA && r != -EOPNOTSUPP) {
1692 *exit_status = EXIT_SMACK_PROCESS_LABEL;
1693 return r;
1694 }
1695
1696 r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL);
1697 if (r < 0) {
1698 *exit_status = EXIT_SMACK_PROCESS_LABEL;
1699 return r;
1700 }
1701 }
1702 #endif
1703 #endif
1704 #ifdef HAVE_PAM
1705 if (context->pam_name && username) {
1706 r = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
1707 if (r < 0) {
1708 *exit_status = EXIT_PAM;
1709 return r;
1710 }
1711 }
1712 #endif
1713 }
1714
1715 if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) {
1716 r = setup_netns(runtime->netns_storage_socket);
1717 if (r < 0) {
1718 *exit_status = EXIT_NETWORK;
1719 return r;
1720 }
1721 }
1722
1723 needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime);
1724
1725 if (needs_mount_namespace) {
1726 char *tmp = NULL, *var = NULL;
1727
1728 /* The runtime struct only contains the parent
1729 * of the private /tmp, which is
1730 * non-accessible to world users. Inside of it
1731 * there's a /tmp that is sticky, and that's
1732 * the one we want to use here. */
1733
1734 if (context->private_tmp && runtime) {
1735 if (runtime->tmp_dir)
1736 tmp = strjoina(runtime->tmp_dir, "/tmp");
1737 if (runtime->var_tmp_dir)
1738 var = strjoina(runtime->var_tmp_dir, "/tmp");
1739 }
1740
1741 r = setup_namespace(
1742 params->apply_chroot ? context->root_directory : NULL,
1743 context->read_write_dirs,
1744 context->read_only_dirs,
1745 context->inaccessible_dirs,
1746 tmp,
1747 var,
1748 params->bus_endpoint_path,
1749 context->private_devices,
1750 context->protect_home,
1751 context->protect_system,
1752 context->mount_flags);
1753
1754 /* If we couldn't set up the namespace this is
1755 * probably due to a missing capability. In this case,
1756 * silently proceeed. */
1757 if (r == -EPERM || r == -EACCES) {
1758 log_open();
1759 log_unit_debug_errno(unit, r, "Failed to set up namespace, assuming containerized execution, ignoring: %m");
1760 log_close();
1761 } else if (r < 0) {
1762 *exit_status = EXIT_NAMESPACE;
1763 return r;
1764 }
1765 }
1766
1767 if (context->working_directory_home)
1768 wd = home;
1769 else if (context->working_directory)
1770 wd = context->working_directory;
1771 else
1772 wd = "/";
1773
1774 if (params->apply_chroot) {
1775 if (!needs_mount_namespace && context->root_directory)
1776 if (chroot(context->root_directory) < 0) {
1777 *exit_status = EXIT_CHROOT;
1778 return -errno;
1779 }
1780
1781 if (chdir(wd) < 0 &&
1782 !context->working_directory_missing_ok) {
1783 *exit_status = EXIT_CHDIR;
1784 return -errno;
1785 }
1786 } else {
1787 const char *d;
1788
1789 d = strjoina(strempty(context->root_directory), "/", strempty(wd));
1790 if (chdir(d) < 0 &&
1791 !context->working_directory_missing_ok) {
1792 *exit_status = EXIT_CHDIR;
1793 return -errno;
1794 }
1795 }
1796
1797 #ifdef HAVE_SELINUX
1798 if (params->apply_permissions && mac_selinux_use() && params->selinux_context_net && socket_fd >= 0) {
1799 r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net);
1800 if (r < 0) {
1801 *exit_status = EXIT_SELINUX_CONTEXT;
1802 return r;
1803 }
1804 }
1805 #endif
1806
1807 /* We repeat the fd closing here, to make sure that
1808 * nothing is leaked from the PAM modules. Note that
1809 * we are more aggressive this time since socket_fd
1810 * and the netns fds we don't need anymore. The custom
1811 * endpoint fd was needed to upload the policy and can
1812 * now be closed as well. */
1813 r = close_all_fds(fds, n_fds);
1814 if (r >= 0)
1815 r = shift_fds(fds, n_fds);
1816 if (r >= 0)
1817 r = flags_fds(fds, n_fds, context->non_blocking);
1818 if (r < 0) {
1819 *exit_status = EXIT_FDS;
1820 return r;
1821 }
1822
1823 if (params->apply_permissions) {
1824
1825 for (i = 0; i < _RLIMIT_MAX; i++) {
1826 if (!context->rlimit[i])
1827 continue;
1828
1829 if (setrlimit_closest(i, context->rlimit[i]) < 0) {
1830 *exit_status = EXIT_LIMITS;
1831 return -errno;
1832 }
1833 }
1834
1835 if (context->capability_bounding_set_drop) {
1836 r = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
1837 if (r < 0) {
1838 *exit_status = EXIT_CAPABILITIES;
1839 return r;
1840 }
1841 }
1842
1843 if (context->user) {
1844 r = enforce_user(context, uid);
1845 if (r < 0) {
1846 *exit_status = EXIT_USER;
1847 return r;
1848 }
1849 }
1850
1851 /* PR_GET_SECUREBITS is not privileged, while
1852 * PR_SET_SECUREBITS is. So to suppress
1853 * potential EPERMs we'll try not to call
1854 * PR_SET_SECUREBITS unless necessary. */
1855 if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
1856 if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
1857 *exit_status = EXIT_SECUREBITS;
1858 return -errno;
1859 }
1860
1861 if (context->capabilities)
1862 if (cap_set_proc(context->capabilities) < 0) {
1863 *exit_status = EXIT_CAPABILITIES;
1864 return -errno;
1865 }
1866
1867 if (context->no_new_privileges)
1868 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
1869 *exit_status = EXIT_NO_NEW_PRIVILEGES;
1870 return -errno;
1871 }
1872
1873 #ifdef HAVE_SECCOMP
1874 if (context->address_families_whitelist ||
1875 !set_isempty(context->address_families)) {
1876 r = apply_address_families(context);
1877 if (r < 0) {
1878 *exit_status = EXIT_ADDRESS_FAMILIES;
1879 return r;
1880 }
1881 }
1882
1883 if (context->syscall_whitelist ||
1884 !set_isempty(context->syscall_filter) ||
1885 !set_isempty(context->syscall_archs)) {
1886 r = apply_seccomp(context);
1887 if (r < 0) {
1888 *exit_status = EXIT_SECCOMP;
1889 return r;
1890 }
1891 }
1892 #endif
1893
1894 #ifdef HAVE_SELINUX
1895 if (mac_selinux_use()) {
1896 char *exec_context = mac_selinux_context_net ?: context->selinux_context;
1897
1898 if (exec_context) {
1899 r = setexeccon(exec_context);
1900 if (r < 0) {
1901 *exit_status = EXIT_SELINUX_CONTEXT;
1902 return r;
1903 }
1904 }
1905 }
1906 #endif
1907
1908 #ifdef HAVE_APPARMOR
1909 if (context->apparmor_profile && mac_apparmor_use()) {
1910 r = aa_change_onexec(context->apparmor_profile);
1911 if (r < 0 && !context->apparmor_profile_ignore) {
1912 *exit_status = EXIT_APPARMOR_PROFILE;
1913 return -errno;
1914 }
1915 }
1916 #endif
1917 }
1918
1919 r = build_environment(context, n_fds, params->fd_names, params->watchdog_usec, home, username, shell, &our_env);
1920 if (r < 0) {
1921 *exit_status = EXIT_MEMORY;
1922 return r;
1923 }
1924
1925 final_env = strv_env_merge(5,
1926 params->environment,
1927 our_env,
1928 context->environment,
1929 files_env,
1930 pam_env,
1931 NULL);
1932 if (!final_env) {
1933 *exit_status = EXIT_MEMORY;
1934 return -ENOMEM;
1935 }
1936
1937 final_argv = replace_env_argv(argv, final_env);
1938 if (!final_argv) {
1939 *exit_status = EXIT_MEMORY;
1940 return -ENOMEM;
1941 }
1942
1943 final_env = strv_env_clean(final_env);
1944
1945 if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
1946 _cleanup_free_ char *line;
1947
1948 line = exec_command_line(final_argv);
1949 if (line) {
1950 log_open();
1951 log_struct(LOG_DEBUG,
1952 LOG_UNIT_ID(unit),
1953 "EXECUTABLE=%s", command->path,
1954 LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
1955 NULL);
1956 log_close();
1957 }
1958 }
1959
1960 execve(command->path, final_argv, final_env);
1961 *exit_status = EXIT_EXEC;
1962 return -errno;
1963 }
1964
1965 int exec_spawn(Unit *unit,
1966 ExecCommand *command,
1967 const ExecContext *context,
1968 const ExecParameters *params,
1969 ExecRuntime *runtime,
1970 pid_t *ret) {
1971
1972 _cleanup_strv_free_ char **files_env = NULL;
1973 int *fds = NULL; unsigned n_fds = 0;
1974 _cleanup_free_ char *line = NULL;
1975 int socket_fd, r;
1976 char **argv;
1977 pid_t pid;
1978
1979 assert(unit);
1980 assert(command);
1981 assert(context);
1982 assert(ret);
1983 assert(params);
1984 assert(params->fds || params->n_fds <= 0);
1985
1986 if (context->std_input == EXEC_INPUT_SOCKET ||
1987 context->std_output == EXEC_OUTPUT_SOCKET ||
1988 context->std_error == EXEC_OUTPUT_SOCKET) {
1989
1990 if (params->n_fds != 1) {
1991 log_unit_error(unit, "Got more than one socket.");
1992 return -EINVAL;
1993 }
1994
1995 socket_fd = params->fds[0];
1996 } else {
1997 socket_fd = -1;
1998 fds = params->fds;
1999 n_fds = params->n_fds;
2000 }
2001
2002 r = exec_context_load_environment(unit, context, &files_env);
2003 if (r < 0)
2004 return log_unit_error_errno(unit, r, "Failed to load environment files: %m");
2005
2006 argv = params->argv ?: command->argv;
2007 line = exec_command_line(argv);
2008 if (!line)
2009 return log_oom();
2010
2011 log_struct(LOG_DEBUG,
2012 LOG_UNIT_ID(unit),
2013 LOG_UNIT_MESSAGE(unit, "About to execute: %s", line),
2014 "EXECUTABLE=%s", command->path,
2015 NULL);
2016 pid = fork();
2017 if (pid < 0)
2018 return log_unit_error_errno(unit, r, "Failed to fork: %m");
2019
2020 if (pid == 0) {
2021 int exit_status;
2022
2023 r = exec_child(unit,
2024 command,
2025 context,
2026 params,
2027 runtime,
2028 argv,
2029 socket_fd,
2030 fds, n_fds,
2031 files_env,
2032 &exit_status);
2033 if (r < 0) {
2034 log_open();
2035 log_struct_errno(LOG_ERR, r,
2036 LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
2037 LOG_UNIT_ID(unit),
2038 LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
2039 exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD),
2040 command->path),
2041 "EXECUTABLE=%s", command->path,
2042 NULL);
2043 }
2044
2045 _exit(exit_status);
2046 }
2047
2048 log_unit_debug(unit, "Forked %s as "PID_FMT, command->path, pid);
2049
2050 /* We add the new process to the cgroup both in the child (so
2051 * that we can be sure that no user code is ever executed
2052 * outside of the cgroup) and in the parent (so that we can be
2053 * sure that when we kill the cgroup the process will be
2054 * killed too). */
2055 if (params->cgroup_path)
2056 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, pid);
2057
2058 exec_status_start(&command->exec_status, pid);
2059
2060 *ret = pid;
2061 return 0;
2062 }
2063
2064 void exec_context_init(ExecContext *c) {
2065 assert(c);
2066
2067 c->umask = 0022;
2068 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
2069 c->cpu_sched_policy = SCHED_OTHER;
2070 c->syslog_priority = LOG_DAEMON|LOG_INFO;
2071 c->syslog_level_prefix = true;
2072 c->ignore_sigpipe = true;
2073 c->timer_slack_nsec = NSEC_INFINITY;
2074 c->personality = PERSONALITY_INVALID;
2075 c->runtime_directory_mode = 0755;
2076 }
2077
2078 void exec_context_done(ExecContext *c) {
2079 unsigned l;
2080
2081 assert(c);
2082
2083 c->environment = strv_free(c->environment);
2084 c->environment_files = strv_free(c->environment_files);
2085
2086 for (l = 0; l < ELEMENTSOF(c->rlimit); l++)
2087 c->rlimit[l] = mfree(c->rlimit[l]);
2088
2089 c->working_directory = mfree(c->working_directory);
2090 c->root_directory = mfree(c->root_directory);
2091 c->tty_path = mfree(c->tty_path);
2092 c->syslog_identifier = mfree(c->syslog_identifier);
2093 c->user = mfree(c->user);
2094 c->group = mfree(c->group);
2095
2096 c->supplementary_groups = strv_free(c->supplementary_groups);
2097
2098 c->pam_name = mfree(c->pam_name);
2099
2100 if (c->capabilities) {
2101 cap_free(c->capabilities);
2102 c->capabilities = NULL;
2103 }
2104
2105 c->read_only_dirs = strv_free(c->read_only_dirs);
2106 c->read_write_dirs = strv_free(c->read_write_dirs);
2107 c->inaccessible_dirs = strv_free(c->inaccessible_dirs);
2108
2109 if (c->cpuset)
2110 CPU_FREE(c->cpuset);
2111
2112 c->utmp_id = mfree(c->utmp_id);
2113 c->selinux_context = mfree(c->selinux_context);
2114 c->apparmor_profile = mfree(c->apparmor_profile);
2115
2116 c->syscall_filter = set_free(c->syscall_filter);
2117 c->syscall_archs = set_free(c->syscall_archs);
2118 c->address_families = set_free(c->address_families);
2119
2120 c->runtime_directory = strv_free(c->runtime_directory);
2121
2122 bus_endpoint_free(c->bus_endpoint);
2123 c->bus_endpoint = NULL;
2124 }
2125
2126 int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_prefix) {
2127 char **i;
2128
2129 assert(c);
2130
2131 if (!runtime_prefix)
2132 return 0;
2133
2134 STRV_FOREACH(i, c->runtime_directory) {
2135 _cleanup_free_ char *p;
2136
2137 p = strjoin(runtime_prefix, "/", *i, NULL);
2138 if (!p)
2139 return -ENOMEM;
2140
2141 /* We execute this synchronously, since we need to be
2142 * sure this is gone when we start the service
2143 * next. */
2144 (void) rm_rf(p, REMOVE_ROOT);
2145 }
2146
2147 return 0;
2148 }
2149
2150 void exec_command_done(ExecCommand *c) {
2151 assert(c);
2152
2153 c->path = mfree(c->path);
2154
2155 c->argv = strv_free(c->argv);
2156 }
2157
2158 void exec_command_done_array(ExecCommand *c, unsigned n) {
2159 unsigned i;
2160
2161 for (i = 0; i < n; i++)
2162 exec_command_done(c+i);
2163 }
2164
2165 ExecCommand* exec_command_free_list(ExecCommand *c) {
2166 ExecCommand *i;
2167
2168 while ((i = c)) {
2169 LIST_REMOVE(command, c, i);
2170 exec_command_done(i);
2171 free(i);
2172 }
2173
2174 return NULL;
2175 }
2176
2177 void exec_command_free_array(ExecCommand **c, unsigned n) {
2178 unsigned i;
2179
2180 for (i = 0; i < n; i++)
2181 c[i] = exec_command_free_list(c[i]);
2182 }
2183
2184 typedef struct InvalidEnvInfo {
2185 Unit *unit;
2186 const char *path;
2187 } InvalidEnvInfo;
2188
2189 static void invalid_env(const char *p, void *userdata) {
2190 InvalidEnvInfo *info = userdata;
2191
2192 log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path);
2193 }
2194
2195 int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
2196 char **i, **r = NULL;
2197
2198 assert(c);
2199 assert(l);
2200
2201 STRV_FOREACH(i, c->environment_files) {
2202 char *fn;
2203 int k;
2204 bool ignore = false;
2205 char **p;
2206 _cleanup_globfree_ glob_t pglob = {};
2207 int count, n;
2208
2209 fn = *i;
2210
2211 if (fn[0] == '-') {
2212 ignore = true;
2213 fn ++;
2214 }
2215
2216 if (!path_is_absolute(fn)) {
2217 if (ignore)
2218 continue;
2219
2220 strv_free(r);
2221 return -EINVAL;
2222 }
2223
2224 /* Filename supports globbing, take all matching files */
2225 errno = 0;
2226 if (glob(fn, 0, NULL, &pglob) != 0) {
2227 if (ignore)
2228 continue;
2229
2230 strv_free(r);
2231 return errno ? -errno : -EINVAL;
2232 }
2233 count = pglob.gl_pathc;
2234 if (count == 0) {
2235 if (ignore)
2236 continue;
2237
2238 strv_free(r);
2239 return -EINVAL;
2240 }
2241 for (n = 0; n < count; n++) {
2242 k = load_env_file(NULL, pglob.gl_pathv[n], NULL, &p);
2243 if (k < 0) {
2244 if (ignore)
2245 continue;
2246
2247 strv_free(r);
2248 return k;
2249 }
2250 /* Log invalid environment variables with filename */
2251 if (p) {
2252 InvalidEnvInfo info = {
2253 .unit = unit,
2254 .path = pglob.gl_pathv[n]
2255 };
2256
2257 p = strv_env_clean_with_callback(p, invalid_env, &info);
2258 }
2259
2260 if (r == NULL)
2261 r = p;
2262 else {
2263 char **m;
2264
2265 m = strv_env_merge(2, r, p);
2266 strv_free(r);
2267 strv_free(p);
2268 if (!m)
2269 return -ENOMEM;
2270
2271 r = m;
2272 }
2273 }
2274 }
2275
2276 *l = r;
2277
2278 return 0;
2279 }
2280
2281 static bool tty_may_match_dev_console(const char *tty) {
2282 _cleanup_free_ char *active = NULL;
2283 char *console;
2284
2285 if (startswith(tty, "/dev/"))
2286 tty += 5;
2287
2288 /* trivial identity? */
2289 if (streq(tty, "console"))
2290 return true;
2291
2292 console = resolve_dev_console(&active);
2293 /* if we could not resolve, assume it may */
2294 if (!console)
2295 return true;
2296
2297 /* "tty0" means the active VC, so it may be the same sometimes */
2298 return streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty));
2299 }
2300
2301 bool exec_context_may_touch_console(ExecContext *ec) {
2302 return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate ||
2303 is_terminal_input(ec->std_input) ||
2304 is_terminal_output(ec->std_output) ||
2305 is_terminal_output(ec->std_error)) &&
2306 tty_may_match_dev_console(tty_path(ec));
2307 }
2308
2309 static void strv_fprintf(FILE *f, char **l) {
2310 char **g;
2311
2312 assert(f);
2313
2314 STRV_FOREACH(g, l)
2315 fprintf(f, " %s", *g);
2316 }
2317
2318 void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
2319 char **e, **d;
2320 unsigned i;
2321
2322 assert(c);
2323 assert(f);
2324
2325 prefix = strempty(prefix);
2326
2327 fprintf(f,
2328 "%sUMask: %04o\n"
2329 "%sWorkingDirectory: %s\n"
2330 "%sRootDirectory: %s\n"
2331 "%sNonBlocking: %s\n"
2332 "%sPrivateTmp: %s\n"
2333 "%sPrivateNetwork: %s\n"
2334 "%sPrivateDevices: %s\n"
2335 "%sProtectHome: %s\n"
2336 "%sProtectSystem: %s\n"
2337 "%sIgnoreSIGPIPE: %s\n",
2338 prefix, c->umask,
2339 prefix, c->working_directory ? c->working_directory : "/",
2340 prefix, c->root_directory ? c->root_directory : "/",
2341 prefix, yes_no(c->non_blocking),
2342 prefix, yes_no(c->private_tmp),
2343 prefix, yes_no(c->private_network),
2344 prefix, yes_no(c->private_devices),
2345 prefix, protect_home_to_string(c->protect_home),
2346 prefix, protect_system_to_string(c->protect_system),
2347 prefix, yes_no(c->ignore_sigpipe));
2348
2349 STRV_FOREACH(e, c->environment)
2350 fprintf(f, "%sEnvironment: %s\n", prefix, *e);
2351
2352 STRV_FOREACH(e, c->environment_files)
2353 fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
2354
2355 fprintf(f, "%sRuntimeDirectoryMode: %04o\n", prefix, c->runtime_directory_mode);
2356
2357 STRV_FOREACH(d, c->runtime_directory)
2358 fprintf(f, "%sRuntimeDirectory: %s\n", prefix, *d);
2359
2360 if (c->nice_set)
2361 fprintf(f,
2362 "%sNice: %i\n",
2363 prefix, c->nice);
2364
2365 if (c->oom_score_adjust_set)
2366 fprintf(f,
2367 "%sOOMScoreAdjust: %i\n",
2368 prefix, c->oom_score_adjust);
2369
2370 for (i = 0; i < RLIM_NLIMITS; i++)
2371 if (c->rlimit[i])
2372 fprintf(f, "%s%s: "RLIM_FMT"\n",
2373 prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
2374
2375 if (c->ioprio_set) {
2376 _cleanup_free_ char *class_str = NULL;
2377
2378 ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
2379 fprintf(f,
2380 "%sIOSchedulingClass: %s\n"
2381 "%sIOPriority: %i\n",
2382 prefix, strna(class_str),
2383 prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
2384 }
2385
2386 if (c->cpu_sched_set) {
2387 _cleanup_free_ char *policy_str = NULL;
2388
2389 sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
2390 fprintf(f,
2391 "%sCPUSchedulingPolicy: %s\n"
2392 "%sCPUSchedulingPriority: %i\n"
2393 "%sCPUSchedulingResetOnFork: %s\n",
2394 prefix, strna(policy_str),
2395 prefix, c->cpu_sched_priority,
2396 prefix, yes_no(c->cpu_sched_reset_on_fork));
2397 }
2398
2399 if (c->cpuset) {
2400 fprintf(f, "%sCPUAffinity:", prefix);
2401 for (i = 0; i < c->cpuset_ncpus; i++)
2402 if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
2403 fprintf(f, " %u", i);
2404 fputs("\n", f);
2405 }
2406
2407 if (c->timer_slack_nsec != NSEC_INFINITY)
2408 fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, c->timer_slack_nsec);
2409
2410 fprintf(f,
2411 "%sStandardInput: %s\n"
2412 "%sStandardOutput: %s\n"
2413 "%sStandardError: %s\n",
2414 prefix, exec_input_to_string(c->std_input),
2415 prefix, exec_output_to_string(c->std_output),
2416 prefix, exec_output_to_string(c->std_error));
2417
2418 if (c->tty_path)
2419 fprintf(f,
2420 "%sTTYPath: %s\n"
2421 "%sTTYReset: %s\n"
2422 "%sTTYVHangup: %s\n"
2423 "%sTTYVTDisallocate: %s\n",
2424 prefix, c->tty_path,
2425 prefix, yes_no(c->tty_reset),
2426 prefix, yes_no(c->tty_vhangup),
2427 prefix, yes_no(c->tty_vt_disallocate));
2428
2429 if (c->std_output == EXEC_OUTPUT_SYSLOG ||
2430 c->std_output == EXEC_OUTPUT_KMSG ||
2431 c->std_output == EXEC_OUTPUT_JOURNAL ||
2432 c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
2433 c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
2434 c->std_output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE ||
2435 c->std_error == EXEC_OUTPUT_SYSLOG ||
2436 c->std_error == EXEC_OUTPUT_KMSG ||
2437 c->std_error == EXEC_OUTPUT_JOURNAL ||
2438 c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
2439 c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
2440 c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE) {
2441
2442 _cleanup_free_ char *fac_str = NULL, *lvl_str = NULL;
2443
2444 log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
2445 log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
2446
2447 fprintf(f,
2448 "%sSyslogFacility: %s\n"
2449 "%sSyslogLevel: %s\n",
2450 prefix, strna(fac_str),
2451 prefix, strna(lvl_str));
2452 }
2453
2454 if (c->capabilities) {
2455 _cleanup_cap_free_charp_ char *t;
2456
2457 t = cap_to_text(c->capabilities, NULL);
2458 if (t)
2459 fprintf(f, "%sCapabilities: %s\n", prefix, t);
2460 }
2461
2462 if (c->secure_bits)
2463 fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
2464 prefix,
2465 (c->secure_bits & 1<<SECURE_KEEP_CAPS) ? " keep-caps" : "",
2466 (c->secure_bits & 1<<SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
2467 (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
2468 (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
2469 (c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
2470 (c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
2471
2472 if (c->capability_bounding_set_drop) {
2473 unsigned long l;
2474 fprintf(f, "%sCapabilityBoundingSet:", prefix);
2475
2476 for (l = 0; l <= cap_last_cap(); l++)
2477 if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l)))
2478 fprintf(f, " %s", strna(capability_to_name(l)));
2479
2480 fputs("\n", f);
2481 }
2482
2483 if (c->user)
2484 fprintf(f, "%sUser: %s\n", prefix, c->user);
2485 if (c->group)
2486 fprintf(f, "%sGroup: %s\n", prefix, c->group);
2487
2488 if (strv_length(c->supplementary_groups) > 0) {
2489 fprintf(f, "%sSupplementaryGroups:", prefix);
2490 strv_fprintf(f, c->supplementary_groups);
2491 fputs("\n", f);
2492 }
2493
2494 if (c->pam_name)
2495 fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
2496
2497 if (strv_length(c->read_write_dirs) > 0) {
2498 fprintf(f, "%sReadWriteDirs:", prefix);
2499 strv_fprintf(f, c->read_write_dirs);
2500 fputs("\n", f);
2501 }
2502
2503 if (strv_length(c->read_only_dirs) > 0) {
2504 fprintf(f, "%sReadOnlyDirs:", prefix);
2505 strv_fprintf(f, c->read_only_dirs);
2506 fputs("\n", f);
2507 }
2508
2509 if (strv_length(c->inaccessible_dirs) > 0) {
2510 fprintf(f, "%sInaccessibleDirs:", prefix);
2511 strv_fprintf(f, c->inaccessible_dirs);
2512 fputs("\n", f);
2513 }
2514
2515 if (c->utmp_id)
2516 fprintf(f,
2517 "%sUtmpIdentifier: %s\n",
2518 prefix, c->utmp_id);
2519
2520 if (c->selinux_context)
2521 fprintf(f,
2522 "%sSELinuxContext: %s%s\n",
2523 prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context);
2524
2525 if (c->personality != PERSONALITY_INVALID)
2526 fprintf(f,
2527 "%sPersonality: %s\n",
2528 prefix, strna(personality_to_string(c->personality)));
2529
2530 if (c->syscall_filter) {
2531 #ifdef HAVE_SECCOMP
2532 Iterator j;
2533 void *id;
2534 bool first = true;
2535 #endif
2536
2537 fprintf(f,
2538 "%sSystemCallFilter: ",
2539 prefix);
2540
2541 if (!c->syscall_whitelist)
2542 fputc('~', f);
2543
2544 #ifdef HAVE_SECCOMP
2545 SET_FOREACH(id, c->syscall_filter, j) {
2546 _cleanup_free_ char *name = NULL;
2547
2548 if (first)
2549 first = false;
2550 else
2551 fputc(' ', f);
2552
2553 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
2554 fputs(strna(name), f);
2555 }
2556 #endif
2557
2558 fputc('\n', f);
2559 }
2560
2561 if (c->syscall_archs) {
2562 #ifdef HAVE_SECCOMP
2563 Iterator j;
2564 void *id;
2565 #endif
2566
2567 fprintf(f,
2568 "%sSystemCallArchitectures:",
2569 prefix);
2570
2571 #ifdef HAVE_SECCOMP
2572 SET_FOREACH(id, c->syscall_archs, j)
2573 fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1)));
2574 #endif
2575 fputc('\n', f);
2576 }
2577
2578 if (c->syscall_errno != 0)
2579 fprintf(f,
2580 "%sSystemCallErrorNumber: %s\n",
2581 prefix, strna(errno_to_name(c->syscall_errno)));
2582
2583 if (c->apparmor_profile)
2584 fprintf(f,
2585 "%sAppArmorProfile: %s%s\n",
2586 prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile);
2587 }
2588
2589 bool exec_context_maintains_privileges(ExecContext *c) {
2590 assert(c);
2591
2592 /* Returns true if the process forked off would run run under
2593 * an unchanged UID or as root. */
2594
2595 if (!c->user)
2596 return true;
2597
2598 if (streq(c->user, "root") || streq(c->user, "0"))
2599 return true;
2600
2601 return false;
2602 }
2603
2604 void exec_status_start(ExecStatus *s, pid_t pid) {
2605 assert(s);
2606
2607 zero(*s);
2608 s->pid = pid;
2609 dual_timestamp_get(&s->start_timestamp);
2610 }
2611
2612 void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status) {
2613 assert(s);
2614
2615 if (s->pid && s->pid != pid)
2616 zero(*s);
2617
2618 s->pid = pid;
2619 dual_timestamp_get(&s->exit_timestamp);
2620
2621 s->code = code;
2622 s->status = status;
2623
2624 if (context) {
2625 if (context->utmp_id)
2626 utmp_put_dead_process(context->utmp_id, pid, code, status);
2627
2628 exec_context_tty_reset(context);
2629 }
2630 }
2631
2632 void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
2633 char buf[FORMAT_TIMESTAMP_MAX];
2634
2635 assert(s);
2636 assert(f);
2637
2638 if (s->pid <= 0)
2639 return;
2640
2641 prefix = strempty(prefix);
2642
2643 fprintf(f,
2644 "%sPID: "PID_FMT"\n",
2645 prefix, s->pid);
2646
2647 if (s->start_timestamp.realtime > 0)
2648 fprintf(f,
2649 "%sStart Timestamp: %s\n",
2650 prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
2651
2652 if (s->exit_timestamp.realtime > 0)
2653 fprintf(f,
2654 "%sExit Timestamp: %s\n"
2655 "%sExit Code: %s\n"
2656 "%sExit Status: %i\n",
2657 prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
2658 prefix, sigchld_code_to_string(s->code),
2659 prefix, s->status);
2660 }
2661
2662 char *exec_command_line(char **argv) {
2663 size_t k;
2664 char *n, *p, **a;
2665 bool first = true;
2666
2667 assert(argv);
2668
2669 k = 1;
2670 STRV_FOREACH(a, argv)
2671 k += strlen(*a)+3;
2672
2673 if (!(n = new(char, k)))
2674 return NULL;
2675
2676 p = n;
2677 STRV_FOREACH(a, argv) {
2678
2679 if (!first)
2680 *(p++) = ' ';
2681 else
2682 first = false;
2683
2684 if (strpbrk(*a, WHITESPACE)) {
2685 *(p++) = '\'';
2686 p = stpcpy(p, *a);
2687 *(p++) = '\'';
2688 } else
2689 p = stpcpy(p, *a);
2690
2691 }
2692
2693 *p = 0;
2694
2695 /* FIXME: this doesn't really handle arguments that have
2696 * spaces and ticks in them */
2697
2698 return n;
2699 }
2700
2701 void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
2702 _cleanup_free_ char *cmd = NULL;
2703 const char *prefix2;
2704
2705 assert(c);
2706 assert(f);
2707
2708 prefix = strempty(prefix);
2709 prefix2 = strjoina(prefix, "\t");
2710
2711 cmd = exec_command_line(c->argv);
2712 fprintf(f,
2713 "%sCommand Line: %s\n",
2714 prefix, cmd ? cmd : strerror(ENOMEM));
2715
2716 exec_status_dump(&c->exec_status, f, prefix2);
2717 }
2718
2719 void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
2720 assert(f);
2721
2722 prefix = strempty(prefix);
2723
2724 LIST_FOREACH(command, c, c)
2725 exec_command_dump(c, f, prefix);
2726 }
2727
2728 void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
2729 ExecCommand *end;
2730
2731 assert(l);
2732 assert(e);
2733
2734 if (*l) {
2735 /* It's kind of important, that we keep the order here */
2736 LIST_FIND_TAIL(command, *l, end);
2737 LIST_INSERT_AFTER(command, *l, end, e);
2738 } else
2739 *l = e;
2740 }
2741
2742 int exec_command_set(ExecCommand *c, const char *path, ...) {
2743 va_list ap;
2744 char **l, *p;
2745
2746 assert(c);
2747 assert(path);
2748
2749 va_start(ap, path);
2750 l = strv_new_ap(path, ap);
2751 va_end(ap);
2752
2753 if (!l)
2754 return -ENOMEM;
2755
2756 p = strdup(path);
2757 if (!p) {
2758 strv_free(l);
2759 return -ENOMEM;
2760 }
2761
2762 free(c->path);
2763 c->path = p;
2764
2765 strv_free(c->argv);
2766 c->argv = l;
2767
2768 return 0;
2769 }
2770
2771 int exec_command_append(ExecCommand *c, const char *path, ...) {
2772 _cleanup_strv_free_ char **l = NULL;
2773 va_list ap;
2774 int r;
2775
2776 assert(c);
2777 assert(path);
2778
2779 va_start(ap, path);
2780 l = strv_new_ap(path, ap);
2781 va_end(ap);
2782
2783 if (!l)
2784 return -ENOMEM;
2785
2786 r = strv_extend_strv(&c->argv, l, false);
2787 if (r < 0)
2788 return r;
2789
2790 return 0;
2791 }
2792
2793
2794 static int exec_runtime_allocate(ExecRuntime **rt) {
2795
2796 if (*rt)
2797 return 0;
2798
2799 *rt = new0(ExecRuntime, 1);
2800 if (!*rt)
2801 return -ENOMEM;
2802
2803 (*rt)->n_ref = 1;
2804 (*rt)->netns_storage_socket[0] = (*rt)->netns_storage_socket[1] = -1;
2805
2806 return 0;
2807 }
2808
2809 int exec_runtime_make(ExecRuntime **rt, ExecContext *c, const char *id) {
2810 int r;
2811
2812 assert(rt);
2813 assert(c);
2814 assert(id);
2815
2816 if (*rt)
2817 return 1;
2818
2819 if (!c->private_network && !c->private_tmp)
2820 return 0;
2821
2822 r = exec_runtime_allocate(rt);
2823 if (r < 0)
2824 return r;
2825
2826 if (c->private_network && (*rt)->netns_storage_socket[0] < 0) {
2827 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, (*rt)->netns_storage_socket) < 0)
2828 return -errno;
2829 }
2830
2831 if (c->private_tmp && !(*rt)->tmp_dir) {
2832 r = setup_tmp_dirs(id, &(*rt)->tmp_dir, &(*rt)->var_tmp_dir);
2833 if (r < 0)
2834 return r;
2835 }
2836
2837 return 1;
2838 }
2839
2840 ExecRuntime *exec_runtime_ref(ExecRuntime *r) {
2841 assert(r);
2842 assert(r->n_ref > 0);
2843
2844 r->n_ref++;
2845 return r;
2846 }
2847
2848 ExecRuntime *exec_runtime_unref(ExecRuntime *r) {
2849
2850 if (!r)
2851 return NULL;
2852
2853 assert(r->n_ref > 0);
2854
2855 r->n_ref--;
2856 if (r->n_ref > 0)
2857 return NULL;
2858
2859 free(r->tmp_dir);
2860 free(r->var_tmp_dir);
2861 safe_close_pair(r->netns_storage_socket);
2862 free(r);
2863
2864 return NULL;
2865 }
2866
2867 int exec_runtime_serialize(Unit *u, ExecRuntime *rt, FILE *f, FDSet *fds) {
2868 assert(u);
2869 assert(f);
2870 assert(fds);
2871
2872 if (!rt)
2873 return 0;
2874
2875 if (rt->tmp_dir)
2876 unit_serialize_item(u, f, "tmp-dir", rt->tmp_dir);
2877
2878 if (rt->var_tmp_dir)
2879 unit_serialize_item(u, f, "var-tmp-dir", rt->var_tmp_dir);
2880
2881 if (rt->netns_storage_socket[0] >= 0) {
2882 int copy;
2883
2884 copy = fdset_put_dup(fds, rt->netns_storage_socket[0]);
2885 if (copy < 0)
2886 return copy;
2887
2888 unit_serialize_item_format(u, f, "netns-socket-0", "%i", copy);
2889 }
2890
2891 if (rt->netns_storage_socket[1] >= 0) {
2892 int copy;
2893
2894 copy = fdset_put_dup(fds, rt->netns_storage_socket[1]);
2895 if (copy < 0)
2896 return copy;
2897
2898 unit_serialize_item_format(u, f, "netns-socket-1", "%i", copy);
2899 }
2900
2901 return 0;
2902 }
2903
2904 int exec_runtime_deserialize_item(Unit *u, ExecRuntime **rt, const char *key, const char *value, FDSet *fds) {
2905 int r;
2906
2907 assert(rt);
2908 assert(key);
2909 assert(value);
2910
2911 if (streq(key, "tmp-dir")) {
2912 char *copy;
2913
2914 r = exec_runtime_allocate(rt);
2915 if (r < 0)
2916 return log_oom();
2917
2918 copy = strdup(value);
2919 if (!copy)
2920 return log_oom();
2921
2922 free((*rt)->tmp_dir);
2923 (*rt)->tmp_dir = copy;
2924
2925 } else if (streq(key, "var-tmp-dir")) {
2926 char *copy;
2927
2928 r = exec_runtime_allocate(rt);
2929 if (r < 0)
2930 return log_oom();
2931
2932 copy = strdup(value);
2933 if (!copy)
2934 return log_oom();
2935
2936 free((*rt)->var_tmp_dir);
2937 (*rt)->var_tmp_dir = copy;
2938
2939 } else if (streq(key, "netns-socket-0")) {
2940 int fd;
2941
2942 r = exec_runtime_allocate(rt);
2943 if (r < 0)
2944 return log_oom();
2945
2946 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
2947 log_unit_debug(u, "Failed to parse netns socket value: %s", value);
2948 else {
2949 safe_close((*rt)->netns_storage_socket[0]);
2950 (*rt)->netns_storage_socket[0] = fdset_remove(fds, fd);
2951 }
2952 } else if (streq(key, "netns-socket-1")) {
2953 int fd;
2954
2955 r = exec_runtime_allocate(rt);
2956 if (r < 0)
2957 return log_oom();
2958
2959 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
2960 log_unit_debug(u, "Failed to parse netns socket value: %s", value);
2961 else {
2962 safe_close((*rt)->netns_storage_socket[1]);
2963 (*rt)->netns_storage_socket[1] = fdset_remove(fds, fd);
2964 }
2965 } else
2966 return 0;
2967
2968 return 1;
2969 }
2970
2971 static void *remove_tmpdir_thread(void *p) {
2972 _cleanup_free_ char *path = p;
2973
2974 (void) rm_rf(path, REMOVE_ROOT|REMOVE_PHYSICAL);
2975 return NULL;
2976 }
2977
2978 void exec_runtime_destroy(ExecRuntime *rt) {
2979 int r;
2980
2981 if (!rt)
2982 return;
2983
2984 /* If there are multiple users of this, let's leave the stuff around */
2985 if (rt->n_ref > 1)
2986 return;
2987
2988 if (rt->tmp_dir) {
2989 log_debug("Spawning thread to nuke %s", rt->tmp_dir);
2990
2991 r = asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
2992 if (r < 0) {
2993 log_warning_errno(r, "Failed to nuke %s: %m", rt->tmp_dir);
2994 free(rt->tmp_dir);
2995 }
2996
2997 rt->tmp_dir = NULL;
2998 }
2999
3000 if (rt->var_tmp_dir) {
3001 log_debug("Spawning thread to nuke %s", rt->var_tmp_dir);
3002
3003 r = asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
3004 if (r < 0) {
3005 log_warning_errno(r, "Failed to nuke %s: %m", rt->var_tmp_dir);
3006 free(rt->var_tmp_dir);
3007 }
3008
3009 rt->var_tmp_dir = NULL;
3010 }
3011
3012 safe_close_pair(rt->netns_storage_socket);
3013 }
3014
3015 static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
3016 [EXEC_INPUT_NULL] = "null",
3017 [EXEC_INPUT_TTY] = "tty",
3018 [EXEC_INPUT_TTY_FORCE] = "tty-force",
3019 [EXEC_INPUT_TTY_FAIL] = "tty-fail",
3020 [EXEC_INPUT_SOCKET] = "socket"
3021 };
3022
3023 DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
3024
3025 static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
3026 [EXEC_OUTPUT_INHERIT] = "inherit",
3027 [EXEC_OUTPUT_NULL] = "null",
3028 [EXEC_OUTPUT_TTY] = "tty",
3029 [EXEC_OUTPUT_SYSLOG] = "syslog",
3030 [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
3031 [EXEC_OUTPUT_KMSG] = "kmsg",
3032 [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
3033 [EXEC_OUTPUT_JOURNAL] = "journal",
3034 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
3035 [EXEC_OUTPUT_SOCKET] = "socket"
3036 };
3037
3038 DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
3039
3040 static const char* const exec_utmp_mode_table[_EXEC_UTMP_MODE_MAX] = {
3041 [EXEC_UTMP_INIT] = "init",
3042 [EXEC_UTMP_LOGIN] = "login",
3043 [EXEC_UTMP_USER] = "user",
3044 };
3045
3046 DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode, ExecUtmpMode);