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