]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/execute.c
make gcc shut up
[thirdparty/systemd.git] / src / core / execute.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5cb5a6ff 2
a7334b09
LP
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
5430f7f2
LP
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
a7334b09
LP
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
5cb5a6ff 22#include <assert.h>
034c6ed7
LP
23#include <dirent.h>
24#include <errno.h>
25#include <fcntl.h>
26#include <unistd.h>
44d8db9e 27#include <string.h>
309bff19 28#include <signal.h>
071830ff
LP
29#include <sys/socket.h>
30#include <sys/un.h>
94f04347 31#include <sys/prctl.h>
66ee3769 32#include <linux/sched.h>
451a074f
LP
33#include <sys/types.h>
34#include <sys/stat.h>
81a2b7ce
LP
35#include <grp.h>
36#include <pwd.h>
15ae422b 37#include <sys/mount.h>
25e870b5 38#include <linux/fs.h>
dd6c17b1 39#include <linux/oom.h>
f2b68789 40#include <sys/poll.h>
2bef10ab 41#include <glob.h>
ac45f971 42#include <sys/personality.h>
d34cd374 43#include <libgen.h>
2b6bf07d 44#undef basename
5cb5a6ff 45
5b6319dc
LP
46#ifdef HAVE_PAM
47#include <security/pam_appl.h>
48#endif
49
7b52a628
MS
50#ifdef HAVE_SELINUX
51#include <selinux/selinux.h>
52#endif
53
17df7223
LP
54#ifdef HAVE_SECCOMP
55#include <seccomp.h>
56#endif
57
5cb5a6ff
LP
58#include "execute.h"
59#include "strv.h"
60#include "macro.h"
d7832d2c 61#include "capability.h"
5cb5a6ff 62#include "util.h"
acbb0225 63#include "log.h"
20ad4cfd 64#include "sd-messages.h"
9eba9da4 65#include "ioprio.h"
94f04347 66#include "securebits.h"
15ae422b 67#include "namespace.h"
df1f0afe 68#include "tcpwrap.h"
d06dacd0 69#include "exit-status.h"
dd6c17b1 70#include "missing.h"
169c1bda 71#include "utmp-wtmp.h"
f6a6225e 72#include "def.h"
9eb977db 73#include "path-util.h"
4d1a6904 74#include "env-util.h"
a5c32cff 75#include "fileio.h"
4ad49000 76#include "unit.h"
f485606b 77#include "async.h"
0d3f7bb3 78#include "selinux-util.h"
17df7223 79#include "errno-list.h"
5cb5a6ff 80
57183d11
LP
81#ifdef HAVE_SECCOMP
82#include "seccomp-util.h"
83#endif
84
e056b01d 85#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
31a7eb86 86#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
e6a26745 87
02a51aba
LP
88/* This assumes there is a 'tty' group */
89#define TTY_MODE 0620
90
531dca78
LP
91#define SNDBUF_SIZE (8*1024*1024)
92
034c6ed7
LP
93static int shift_fds(int fds[], unsigned n_fds) {
94 int start, restart_from;
95
96 if (n_fds <= 0)
97 return 0;
98
a0d40ac5
LP
99 /* Modifies the fds array! (sorts it) */
100
034c6ed7
LP
101 assert(fds);
102
103 start = 0;
104 for (;;) {
105 int i;
106
107 restart_from = -1;
108
109 for (i = start; i < (int) n_fds; i++) {
110 int nfd;
111
112 /* Already at right index? */
113 if (fds[i] == i+3)
114 continue;
115
116 if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0)
117 return -errno;
118
e1f5e051 119 close_nointr_nofail(fds[i]);
034c6ed7
LP
120 fds[i] = nfd;
121
122 /* Hmm, the fd we wanted isn't free? Then
123 * let's remember that and try again from here*/
124 if (nfd != i+3 && restart_from < 0)
125 restart_from = i;
126 }
127
128 if (restart_from < 0)
129 break;
130
131 start = restart_from;
132 }
133
134 return 0;
135}
136
c2748801 137static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
47a71eed 138 unsigned i;
e2c76839 139 int r;
47a71eed
LP
140
141 if (n_fds <= 0)
142 return 0;
143
144 assert(fds);
145
451a074f 146 /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
47a71eed
LP
147
148 for (i = 0; i < n_fds; i++) {
47a71eed 149
e2c76839
LP
150 if ((r = fd_nonblock(fds[i], nonblock)) < 0)
151 return r;
47a71eed 152
451a074f
LP
153 /* We unconditionally drop FD_CLOEXEC from the fds,
154 * since after all we want to pass these fds to our
155 * children */
47a71eed 156
e2c76839
LP
157 if ((r = fd_cloexec(fds[i], false)) < 0)
158 return r;
47a71eed
LP
159 }
160
161 return 0;
162}
163
44a6b1b6 164_pure_ static const char *tty_path(const ExecContext *context) {
80876c20
LP
165 assert(context);
166
167 if (context->tty_path)
168 return context->tty_path;
169
170 return "/dev/console";
171}
172
9588bc32 173static void exec_context_tty_reset(const ExecContext *context) {
6ea832a2
LP
174 assert(context);
175
176 if (context->tty_vhangup)
177 terminal_vhangup(tty_path(context));
178
179 if (context->tty_reset)
180 reset_terminal(tty_path(context));
181
182 if (context->tty_vt_disallocate && context->tty_path)
183 vt_disallocate(context->tty_path);
184}
185
3a1286b6
MS
186static bool is_terminal_output(ExecOutput o) {
187 return
188 o == EXEC_OUTPUT_TTY ||
189 o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
190 o == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
191 o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE;
192}
193
80876c20
LP
194static int open_null_as(int flags, int nfd) {
195 int fd, r;
071830ff 196
80876c20 197 assert(nfd >= 0);
071830ff 198
613b411c
LP
199 fd = open("/dev/null", flags|O_NOCTTY);
200 if (fd < 0)
071830ff
LP
201 return -errno;
202
80876c20
LP
203 if (fd != nfd) {
204 r = dup2(fd, nfd) < 0 ? -errno : nfd;
e1f5e051 205 close_nointr_nofail(fd);
80876c20
LP
206 } else
207 r = nfd;
071830ff 208
80876c20 209 return r;
071830ff
LP
210}
211
62bca2c6 212static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd) {
80876c20 213 int fd, r;
b92bea5d
ZJS
214 union sockaddr_union sa = {
215 .un.sun_family = AF_UNIX,
216 .un.sun_path = "/run/systemd/journal/stdout",
217 };
071830ff
LP
218
219 assert(context);
80876c20
LP
220 assert(output < _EXEC_OUTPUT_MAX);
221 assert(ident);
222 assert(nfd >= 0);
071830ff 223
54fe0cdb
LP
224 fd = socket(AF_UNIX, SOCK_STREAM, 0);
225 if (fd < 0)
80876c20 226 return -errno;
071830ff 227
54fe0cdb
LP
228 r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
229 if (r < 0) {
80876c20
LP
230 close_nointr_nofail(fd);
231 return -errno;
232 }
071830ff 233
80876c20
LP
234 if (shutdown(fd, SHUT_RD) < 0) {
235 close_nointr_nofail(fd);
236 return -errno;
237 }
071830ff 238
531dca78
LP
239 fd_inc_sndbuf(fd, SNDBUF_SIZE);
240
80876c20 241 dprintf(fd,
62bca2c6 242 "%s\n"
80876c20
LP
243 "%s\n"
244 "%i\n"
54fe0cdb
LP
245 "%i\n"
246 "%i\n"
247 "%i\n"
4f4a1dbf 248 "%i\n",
4f4a1dbf 249 context->syslog_identifier ? context->syslog_identifier : ident,
62bca2c6 250 unit_id,
54fe0cdb
LP
251 context->syslog_priority,
252 !!context->syslog_level_prefix,
253 output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
254 output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
3a1286b6 255 is_terminal_output(output));
80876c20
LP
256
257 if (fd != nfd) {
258 r = dup2(fd, nfd) < 0 ? -errno : nfd;
e1f5e051 259 close_nointr_nofail(fd);
80876c20
LP
260 } else
261 r = nfd;
071830ff 262
80876c20
LP
263 return r;
264}
265static int open_terminal_as(const char *path, mode_t mode, int nfd) {
266 int fd, r;
071830ff 267
80876c20
LP
268 assert(path);
269 assert(nfd >= 0);
071830ff 270
80876c20
LP
271 if ((fd = open_terminal(path, mode | O_NOCTTY)) < 0)
272 return fd;
071830ff 273
80876c20
LP
274 if (fd != nfd) {
275 r = dup2(fd, nfd) < 0 ? -errno : nfd;
276 close_nointr_nofail(fd);
277 } else
278 r = nfd;
071830ff 279
80876c20
LP
280 return r;
281}
071830ff 282
80876c20
LP
283static bool is_terminal_input(ExecInput i) {
284 return
285 i == EXEC_INPUT_TTY ||
286 i == EXEC_INPUT_TTY_FORCE ||
287 i == EXEC_INPUT_TTY_FAIL;
288}
071830ff 289
1e3ad081
LP
290static int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
291
292 if (is_terminal_input(std_input) && !apply_tty_stdin)
293 return EXEC_INPUT_NULL;
071830ff 294
03fd9c49 295 if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
4f2d528d
LP
296 return EXEC_INPUT_NULL;
297
03fd9c49 298 return std_input;
4f2d528d
LP
299}
300
03fd9c49 301static int fixup_output(ExecOutput std_output, int socket_fd) {
4f2d528d 302
03fd9c49 303 if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
4f2d528d
LP
304 return EXEC_OUTPUT_INHERIT;
305
03fd9c49 306 return std_output;
4f2d528d
LP
307}
308
1e3ad081 309static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
4f2d528d
LP
310 ExecInput i;
311
312 assert(context);
313
1e3ad081 314 i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
4f2d528d
LP
315
316 switch (i) {
071830ff 317
80876c20
LP
318 case EXEC_INPUT_NULL:
319 return open_null_as(O_RDONLY, STDIN_FILENO);
320
321 case EXEC_INPUT_TTY:
322 case EXEC_INPUT_TTY_FORCE:
323 case EXEC_INPUT_TTY_FAIL: {
324 int fd, r;
071830ff 325
970edce6
ZJS
326 fd = acquire_terminal(tty_path(context),
327 i == EXEC_INPUT_TTY_FAIL,
328 i == EXEC_INPUT_TTY_FORCE,
329 false,
330 (usec_t) -1);
331 if (fd < 0)
80876c20
LP
332 return fd;
333
334 if (fd != STDIN_FILENO) {
335 r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
071830ff 336 close_nointr_nofail(fd);
80876c20
LP
337 } else
338 r = STDIN_FILENO;
339
340 return r;
341 }
342
4f2d528d
LP
343 case EXEC_INPUT_SOCKET:
344 return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
345
80876c20
LP
346 default:
347 assert_not_reached("Unknown input type");
348 }
349}
350
eb17e935 351static int setup_output(const ExecContext *context, int fileno, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
4f2d528d
LP
352 ExecOutput o;
353 ExecInput i;
47c1d80d 354 int r;
4f2d528d 355
80876c20
LP
356 assert(context);
357 assert(ident);
358
1e3ad081 359 i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
03fd9c49 360 o = fixup_output(context->std_output, socket_fd);
4f2d528d 361
eb17e935
MS
362 if (fileno == STDERR_FILENO) {
363 ExecOutput e;
364 e = fixup_output(context->std_error, socket_fd);
80876c20 365
eb17e935
MS
366 /* This expects the input and output are already set up */
367
368 /* Don't change the stderr file descriptor if we inherit all
369 * the way and are not on a tty */
370 if (e == EXEC_OUTPUT_INHERIT &&
371 o == EXEC_OUTPUT_INHERIT &&
372 i == EXEC_INPUT_NULL &&
373 !is_terminal_input(context->std_input) &&
374 getppid () != 1)
375 return fileno;
376
377 /* Duplicate from stdout if possible */
378 if (e == o || e == EXEC_OUTPUT_INHERIT)
379 return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
071830ff 380
eb17e935 381 o = e;
80876c20 382
eb17e935 383 } else if (o == EXEC_OUTPUT_INHERIT) {
21d21ea4
LP
384 /* If input got downgraded, inherit the original value */
385 if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
eb17e935 386 return open_terminal_as(tty_path(context), O_WRONLY, fileno);
21d21ea4 387
acb591e4 388 /* If the input is connected to anything that's not a /dev/null, inherit that... */
ff876e28 389 if (i != EXEC_INPUT_NULL)
eb17e935 390 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
071830ff 391
acb591e4
LP
392 /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
393 if (getppid() != 1)
eb17e935 394 return fileno;
94f04347 395
eb17e935
MS
396 /* We need to open /dev/null here anew, to get the right access mode. */
397 return open_null_as(O_WRONLY, fileno);
071830ff 398 }
94f04347 399
eb17e935 400 switch (o) {
80876c20
LP
401
402 case EXEC_OUTPUT_NULL:
eb17e935 403 return open_null_as(O_WRONLY, fileno);
80876c20
LP
404
405 case EXEC_OUTPUT_TTY:
4f2d528d 406 if (is_terminal_input(i))
eb17e935 407 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
80876c20
LP
408
409 /* We don't reset the terminal if this is just about output */
eb17e935 410 return open_terminal_as(tty_path(context), O_WRONLY, fileno);
80876c20
LP
411
412 case EXEC_OUTPUT_SYSLOG:
28dbc1e8 413 case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
9a6bca7a 414 case EXEC_OUTPUT_KMSG:
28dbc1e8 415 case EXEC_OUTPUT_KMSG_AND_CONSOLE:
706343f4
LP
416 case EXEC_OUTPUT_JOURNAL:
417 case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
eb17e935 418 r = connect_logger_as(context, o, ident, unit_id, fileno);
47c1d80d 419 if (r < 0) {
80cbda35
MS
420 log_struct_unit(LOG_CRIT, unit_id,
421 "MESSAGE=Failed to connect std%s of %s to the journal socket: %s",
eb17e935 422 fileno == STDOUT_FILENO ? "out" : "err",
80cbda35
MS
423 unit_id, strerror(-r),
424 "ERRNO=%d", -r,
425 NULL);
eb17e935 426 r = open_null_as(O_WRONLY, fileno);
47c1d80d
MS
427 }
428 return r;
4f2d528d
LP
429
430 case EXEC_OUTPUT_SOCKET:
431 assert(socket_fd >= 0);
eb17e935 432 return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
94f04347
LP
433
434 default:
80876c20 435 assert_not_reached("Unknown error type");
94f04347 436 }
071830ff
LP
437}
438
02a51aba
LP
439static int chown_terminal(int fd, uid_t uid) {
440 struct stat st;
441
442 assert(fd >= 0);
02a51aba
LP
443
444 /* This might fail. What matters are the results. */
bab45044
LP
445 (void) fchown(fd, uid, -1);
446 (void) fchmod(fd, TTY_MODE);
02a51aba
LP
447
448 if (fstat(fd, &st) < 0)
449 return -errno;
450
d8b4e2e9 451 if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
02a51aba
LP
452 return -EPERM;
453
454 return 0;
455}
456
af6da548 457static int setup_confirm_stdio(int *_saved_stdin,
80876c20
LP
458 int *_saved_stdout) {
459 int fd = -1, saved_stdin, saved_stdout = -1, r;
460
80876c20
LP
461 assert(_saved_stdin);
462 assert(_saved_stdout);
463
af6da548
LP
464 saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
465 if (saved_stdin < 0)
466 return -errno;
80876c20 467
af6da548
LP
468 saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
469 if (saved_stdout < 0) {
470 r = errno;
80876c20
LP
471 goto fail;
472 }
473
af6da548
LP
474 fd = acquire_terminal(
475 "/dev/console",
476 false,
477 false,
478 false,
479 DEFAULT_CONFIRM_USEC);
480 if (fd < 0) {
481 r = fd;
80876c20
LP
482 goto fail;
483 }
484
af6da548
LP
485 r = chown_terminal(fd, getuid());
486 if (r < 0)
02a51aba 487 goto fail;
02a51aba 488
80876c20 489 if (dup2(fd, STDIN_FILENO) < 0) {
af6da548 490 r = -errno;
80876c20
LP
491 goto fail;
492 }
493
494 if (dup2(fd, STDOUT_FILENO) < 0) {
af6da548 495 r = -errno;
80876c20
LP
496 goto fail;
497 }
498
499 if (fd >= 2)
500 close_nointr_nofail(fd);
501
502 *_saved_stdin = saved_stdin;
503 *_saved_stdout = saved_stdout;
504
505 return 0;
506
507fail:
508 if (saved_stdout >= 0)
509 close_nointr_nofail(saved_stdout);
510
511 if (saved_stdin >= 0)
512 close_nointr_nofail(saved_stdin);
513
514 if (fd >= 0)
515 close_nointr_nofail(fd);
516
517 return r;
518}
519
44b601bc 520_printf_(1, 2) static int write_confirm_message(const char *format, ...) {
af6da548
LP
521 int fd;
522 va_list ap;
80876c20 523
af6da548 524 assert(format);
80876c20 525
af6da548
LP
526 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
527 if (fd < 0)
528 return fd;
80876c20 529
af6da548
LP
530 va_start(ap, format);
531 vdprintf(fd, format, ap);
532 va_end(ap);
80876c20 533
af6da548 534 close_nointr_nofail(fd);
80876c20 535
af6da548
LP
536 return 0;
537}
80876c20 538
af6da548
LP
539static int restore_confirm_stdio(int *saved_stdin,
540 int *saved_stdout) {
80876c20 541
af6da548 542 int r = 0;
80876c20 543
af6da548
LP
544 assert(saved_stdin);
545 assert(saved_stdout);
546
547 release_terminal();
548
549 if (*saved_stdin >= 0)
80876c20 550 if (dup2(*saved_stdin, STDIN_FILENO) < 0)
af6da548 551 r = -errno;
80876c20 552
af6da548 553 if (*saved_stdout >= 0)
80876c20 554 if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
af6da548 555 r = -errno;
80876c20 556
af6da548
LP
557 if (*saved_stdin >= 0)
558 close_nointr_nofail(*saved_stdin);
80876c20 559
af6da548
LP
560 if (*saved_stdout >= 0)
561 close_nointr_nofail(*saved_stdout);
562
563 return r;
564}
565
566static int ask_for_confirmation(char *response, char **argv) {
567 int saved_stdout = -1, saved_stdin = -1, r;
568 char *line;
569
570 r = setup_confirm_stdio(&saved_stdin, &saved_stdout);
571 if (r < 0)
572 return r;
573
574 line = exec_command_line(argv);
575 if (!line)
576 return -ENOMEM;
577
578 r = ask(response, "yns", "Execute %s? [Yes, No, Skip] ", line);
579 free(line);
580
581 restore_confirm_stdio(&saved_stdin, &saved_stdout);
582
583 return r;
80876c20
LP
584}
585
81a2b7ce
LP
586static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
587 bool keep_groups = false;
588 int r;
589
590 assert(context);
591
35b8ca3a 592 /* Lookup and set GID and supplementary group list. Here too
81a2b7ce
LP
593 * we avoid NSS lookups for gid=0. */
594
595 if (context->group || username) {
596
4b67834e
LP
597 if (context->group) {
598 const char *g = context->group;
599
600 if ((r = get_group_creds(&g, &gid)) < 0)
81a2b7ce 601 return r;
4b67834e 602 }
81a2b7ce
LP
603
604 /* First step, initialize groups from /etc/groups */
605 if (username && gid != 0) {
606 if (initgroups(username, gid) < 0)
607 return -errno;
608
609 keep_groups = true;
610 }
611
612 /* Second step, set our gids */
613 if (setresgid(gid, gid, gid) < 0)
614 return -errno;
615 }
616
617 if (context->supplementary_groups) {
618 int ngroups_max, k;
619 gid_t *gids;
620 char **i;
621
622 /* Final step, initialize any manually set supplementary groups */
da19d5c1 623 assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
81a2b7ce
LP
624
625 if (!(gids = new(gid_t, ngroups_max)))
626 return -ENOMEM;
627
628 if (keep_groups) {
629 if ((k = getgroups(ngroups_max, gids)) < 0) {
630 free(gids);
631 return -errno;
632 }
633 } else
634 k = 0;
635
636 STRV_FOREACH(i, context->supplementary_groups) {
4b67834e 637 const char *g;
81a2b7ce
LP
638
639 if (k >= ngroups_max) {
640 free(gids);
641 return -E2BIG;
642 }
643
4b67834e
LP
644 g = *i;
645 r = get_group_creds(&g, gids+k);
646 if (r < 0) {
81a2b7ce
LP
647 free(gids);
648 return r;
649 }
650
651 k++;
652 }
653
654 if (setgroups(k, gids) < 0) {
655 free(gids);
656 return -errno;
657 }
658
659 free(gids);
660 }
661
662 return 0;
663}
664
665static int enforce_user(const ExecContext *context, uid_t uid) {
81a2b7ce
LP
666 assert(context);
667
668 /* Sets (but doesn't lookup) the uid and make sure we keep the
669 * capabilities while doing so. */
670
671 if (context->capabilities) {
5ce70e5b 672 _cleanup_cap_free_ cap_t d = NULL;
81a2b7ce
LP
673 static const cap_value_t bits[] = {
674 CAP_SETUID, /* Necessary so that we can run setresuid() below */
675 CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
676 };
677
678 /* First step: If we need to keep capabilities but
679 * drop privileges we need to make sure we keep our
cbb21cca 680 * caps, while we drop privileges. */
693ced48 681 if (uid != 0) {
cbb21cca 682 int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
693ced48
LP
683
684 if (prctl(PR_GET_SECUREBITS) != sb)
685 if (prctl(PR_SET_SECUREBITS, sb) < 0)
686 return -errno;
687 }
81a2b7ce 688
35b8ca3a 689 /* Second step: set the capabilities. This will reduce
81a2b7ce
LP
690 * the capabilities to the minimum we need. */
691
5ce70e5b
ZJS
692 d = cap_dup(context->capabilities);
693 if (!d)
81a2b7ce
LP
694 return -errno;
695
696 if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
5ce70e5b
ZJS
697 cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0)
698 return -errno;
81a2b7ce 699
5ce70e5b
ZJS
700 if (cap_set_proc(d) < 0)
701 return -errno;
81a2b7ce
LP
702 }
703
704 /* Third step: actually set the uids */
705 if (setresuid(uid, uid, uid) < 0)
706 return -errno;
707
708 /* At this point we should have all necessary capabilities but
709 are otherwise a normal user. However, the caps might got
710 corrupted due to the setresuid() so we need clean them up
711 later. This is done outside of this call. */
712
713 return 0;
714}
715
5b6319dc
LP
716#ifdef HAVE_PAM
717
718static int null_conv(
719 int num_msg,
720 const struct pam_message **msg,
721 struct pam_response **resp,
722 void *appdata_ptr) {
723
724 /* We don't support conversations */
725
726 return PAM_CONV_ERR;
727}
728
729static int setup_pam(
730 const char *name,
731 const char *user,
940c5210 732 uid_t uid,
5b6319dc
LP
733 const char *tty,
734 char ***pam_env,
735 int fds[], unsigned n_fds) {
736
737 static const struct pam_conv conv = {
738 .conv = null_conv,
739 .appdata_ptr = NULL
740 };
741
742 pam_handle_t *handle = NULL;
743 sigset_t ss, old_ss;
744 int pam_code = PAM_SUCCESS;
9ba35398 745 int err;
5b6319dc
LP
746 char **e = NULL;
747 bool close_session = false;
748 pid_t pam_pid = 0, parent_pid;
970edce6 749 int flags = 0;
5b6319dc
LP
750
751 assert(name);
752 assert(user);
753 assert(pam_env);
754
755 /* We set up PAM in the parent process, then fork. The child
35b8ca3a 756 * will then stay around until killed via PR_GET_PDEATHSIG or
5b6319dc
LP
757 * systemd via the cgroup logic. It will then remove the PAM
758 * session again. The parent process will exec() the actual
759 * daemon. We do things this way to ensure that the main PID
760 * of the daemon is the one we initially fork()ed. */
761
970edce6
ZJS
762 if (log_get_max_level() < LOG_PRI(LOG_DEBUG))
763 flags |= PAM_SILENT;
764
f546241b
ZJS
765 pam_code = pam_start(name, user, &conv, &handle);
766 if (pam_code != PAM_SUCCESS) {
5b6319dc
LP
767 handle = NULL;
768 goto fail;
769 }
770
f546241b
ZJS
771 if (tty) {
772 pam_code = pam_set_item(handle, PAM_TTY, tty);
773 if (pam_code != PAM_SUCCESS)
5b6319dc 774 goto fail;
f546241b 775 }
5b6319dc 776
970edce6 777 pam_code = pam_acct_mgmt(handle, flags);
f546241b 778 if (pam_code != PAM_SUCCESS)
5b6319dc
LP
779 goto fail;
780
970edce6 781 pam_code = pam_open_session(handle, flags);
f546241b 782 if (pam_code != PAM_SUCCESS)
5b6319dc
LP
783 goto fail;
784
785 close_session = true;
786
f546241b
ZJS
787 e = pam_getenvlist(handle);
788 if (!e) {
5b6319dc
LP
789 pam_code = PAM_BUF_ERR;
790 goto fail;
791 }
792
793 /* Block SIGTERM, so that we know that it won't get lost in
794 * the child */
795 if (sigemptyset(&ss) < 0 ||
796 sigaddset(&ss, SIGTERM) < 0 ||
797 sigprocmask(SIG_BLOCK, &ss, &old_ss) < 0)
798 goto fail;
799
800 parent_pid = getpid();
801
f546241b
ZJS
802 pam_pid = fork();
803 if (pam_pid < 0)
5b6319dc
LP
804 goto fail;
805
806 if (pam_pid == 0) {
807 int sig;
808 int r = EXIT_PAM;
809
810 /* The child's job is to reset the PAM session on
811 * termination */
812
813 /* This string must fit in 10 chars (i.e. the length
5d6b1584
LP
814 * of "/sbin/init"), to look pretty in /bin/ps */
815 rename_process("(sd-pam)");
5b6319dc
LP
816
817 /* Make sure we don't keep open the passed fds in this
818 child. We assume that otherwise only those fds are
819 open here that have been opened by PAM. */
820 close_many(fds, n_fds);
821
940c5210
AK
822 /* Drop privileges - we don't need any to pam_close_session
823 * and this will make PR_SET_PDEATHSIG work in most cases.
824 * If this fails, ignore the error - but expect sd-pam threads
825 * to fail to exit normally */
826 if (setresuid(uid, uid, uid) < 0)
827 log_error("Error: Failed to setresuid() in sd-pam: %s", strerror(-r));
828
829 /* Wait until our parent died. This will only work if
830 * the above setresuid() succeeds, otherwise the kernel
831 * will not allow unprivileged parents kill their privileged
832 * children this way. We rely on the control groups kill logic
5b6319dc
LP
833 * to do the rest for us. */
834 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
835 goto child_finish;
836
837 /* Check if our parent process might already have
838 * died? */
839 if (getppid() == parent_pid) {
3dead8d9
LP
840 for (;;) {
841 if (sigwait(&ss, &sig) < 0) {
842 if (errno == EINTR)
843 continue;
844
845 goto child_finish;
846 }
5b6319dc 847
3dead8d9
LP
848 assert(sig == SIGTERM);
849 break;
850 }
5b6319dc
LP
851 }
852
3dead8d9 853 /* If our parent died we'll end the session */
f546241b 854 if (getppid() != parent_pid) {
970edce6 855 pam_code = pam_close_session(handle, flags);
f546241b 856 if (pam_code != PAM_SUCCESS)
5b6319dc 857 goto child_finish;
f546241b 858 }
5b6319dc
LP
859
860 r = 0;
861
862 child_finish:
970edce6 863 pam_end(handle, pam_code | flags);
5b6319dc
LP
864 _exit(r);
865 }
866
867 /* If the child was forked off successfully it will do all the
868 * cleanups, so forget about the handle here. */
869 handle = NULL;
870
3b8bddde 871 /* Unblock SIGTERM again in the parent */
5b6319dc
LP
872 if (sigprocmask(SIG_SETMASK, &old_ss, NULL) < 0)
873 goto fail;
874
875 /* We close the log explicitly here, since the PAM modules
876 * might have opened it, but we don't want this fd around. */
877 closelog();
878
aa87e624
LP
879 *pam_env = e;
880 e = NULL;
881
5b6319dc
LP
882 return 0;
883
884fail:
970edce6
ZJS
885 if (pam_code != PAM_SUCCESS) {
886 log_error("PAM failed: %s", pam_strerror(handle, pam_code));
9ba35398 887 err = -EPERM; /* PAM errors do not map to errno */
970edce6
ZJS
888 } else {
889 log_error("PAM failed: %m");
9ba35398 890 err = -errno;
970edce6 891 }
9ba35398 892
5b6319dc
LP
893 if (handle) {
894 if (close_session)
970edce6 895 pam_code = pam_close_session(handle, flags);
5b6319dc 896
970edce6 897 pam_end(handle, pam_code | flags);
5b6319dc
LP
898 }
899
900 strv_free(e);
901
902 closelog();
903
430c18ed 904 if (pam_pid > 1) {
5b6319dc 905 kill(pam_pid, SIGTERM);
430c18ed
LP
906 kill(pam_pid, SIGCONT);
907 }
5b6319dc 908
9ba35398 909 return err;
5b6319dc
LP
910}
911#endif
912
5d6b1584
LP
913static void rename_process_from_path(const char *path) {
914 char process_name[11];
915 const char *p;
916 size_t l;
917
918 /* This resulting string must fit in 10 chars (i.e. the length
919 * of "/sbin/init") to look pretty in /bin/ps */
920
2b6bf07d 921 p = basename(path);
5d6b1584
LP
922 if (isempty(p)) {
923 rename_process("(...)");
924 return;
925 }
926
927 l = strlen(p);
928 if (l > 8) {
929 /* The end of the process name is usually more
930 * interesting, since the first bit might just be
931 * "systemd-" */
932 p = p + l - 8;
933 l = 8;
934 }
935
936 process_name[0] = '(';
937 memcpy(process_name+1, p, l);
938 process_name[1+l] = ')';
939 process_name[1+l+1] = 0;
940
941 rename_process(process_name);
942}
943
c0467cf3 944#ifdef HAVE_SECCOMP
17df7223 945
c0467cf3 946static int apply_seccomp(ExecContext *c) {
17df7223
LP
947 uint32_t negative_action, action;
948 scmp_filter_ctx *seccomp;
c0467cf3
RC
949 Iterator i;
950 void *id;
17df7223 951 int r;
8351ceae 952
c0467cf3 953 assert(c);
8351ceae 954
17df7223
LP
955 negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno);
956
957 seccomp = seccomp_init(c->syscall_whitelist ? negative_action : SCMP_ACT_ALLOW);
958 if (!seccomp)
959 return -ENOMEM;
8351ceae 960
e9642be2
LP
961 if (c->syscall_archs) {
962
963 SET_FOREACH(id, c->syscall_archs, i) {
964 r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
965 if (r == -EEXIST)
966 continue;
967 if (r < 0) {
968 seccomp_release(seccomp);
969 return r;
970 }
971 }
972 } else {
973
974 r = seccomp_add_secondary_archs(seccomp);
57183d11
LP
975 if (r < 0) {
976 seccomp_release(seccomp);
977 return r;
978 }
979 }
8351ceae 980
57183d11 981 action = c->syscall_whitelist ? SCMP_ACT_ALLOW : negative_action;
17df7223
LP
982 SET_FOREACH(id, c->syscall_filter, i) {
983 r = seccomp_rule_add(seccomp, action, PTR_TO_INT(id) - 1, 0);
c0467cf3 984 if (r < 0) {
17df7223 985 seccomp_release(seccomp);
c0467cf3 986 return r;
8351ceae 987 }
c0467cf3 988 }
8351ceae 989
17df7223
LP
990 r = seccomp_load(seccomp);
991 seccomp_release(seccomp);
992
993 return r;
8351ceae 994}
c0467cf3 995#endif
8351ceae 996
31a7eb86
ZJS
997static void do_idle_pipe_dance(int idle_pipe[4]) {
998 assert(idle_pipe);
999
1000 if (idle_pipe[1] >= 0)
1001 close_nointr_nofail(idle_pipe[1]);
1002 if (idle_pipe[2] >= 0)
1003 close_nointr_nofail(idle_pipe[2]);
1004
1005 if (idle_pipe[0] >= 0) {
1006 int r;
1007
1008 r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
1009
1010 if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
1011 /* Signal systemd that we are bored and want to continue. */
1012 write(idle_pipe[3], "x", 1);
1013
1014 /* Wait for systemd to react to the signal above. */
1015 fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
1016 }
1017
1018 close_nointr_nofail(idle_pipe[0]);
1019
1020 }
1021
1022 if (idle_pipe[3] >= 0)
1023 close_nointr_nofail(idle_pipe[3]);
1024}
1025
7cae38c4
LP
1026static int build_environment(
1027 ExecContext *c,
1028 unsigned n_fds,
09812eb7 1029 usec_t watchdog_usec,
7cae38c4
LP
1030 const char *home,
1031 const char *username,
1032 const char *shell,
1033 char ***ret) {
1034
1035 _cleanup_strv_free_ char **our_env = NULL;
1036 unsigned n_env = 0;
1037 char *x;
1038
1039 assert(c);
1040 assert(ret);
1041
09812eb7 1042 our_env = new0(char*, 10);
7cae38c4
LP
1043 if (!our_env)
1044 return -ENOMEM;
1045
1046 if (n_fds > 0) {
ccd06097 1047 if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid()) < 0)
7cae38c4
LP
1048 return -ENOMEM;
1049 our_env[n_env++] = x;
1050
1051 if (asprintf(&x, "LISTEN_FDS=%u", n_fds) < 0)
1052 return -ENOMEM;
1053 our_env[n_env++] = x;
1054 }
1055
09812eb7 1056 if (watchdog_usec > 0) {
ccd06097 1057 if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid()) < 0)
09812eb7
LP
1058 return -ENOMEM;
1059 our_env[n_env++] = x;
1060
1061 if (asprintf(&x, "WATCHDOG_USEC=%llu", (unsigned long long) watchdog_usec) < 0)
1062 return -ENOMEM;
1063 our_env[n_env++] = x;
1064 }
1065
7cae38c4
LP
1066 if (home) {
1067 x = strappend("HOME=", home);
1068 if (!x)
1069 return -ENOMEM;
1070 our_env[n_env++] = x;
1071 }
1072
1073 if (username) {
1074 x = strappend("LOGNAME=", username);
1075 if (!x)
1076 return -ENOMEM;
1077 our_env[n_env++] = x;
1078
1079 x = strappend("USER=", username);
1080 if (!x)
1081 return -ENOMEM;
1082 our_env[n_env++] = x;
1083 }
1084
1085 if (shell) {
1086 x = strappend("SHELL=", shell);
1087 if (!x)
1088 return -ENOMEM;
1089 our_env[n_env++] = x;
1090 }
1091
1092 if (is_terminal_input(c->std_input) ||
1093 c->std_output == EXEC_OUTPUT_TTY ||
1094 c->std_error == EXEC_OUTPUT_TTY ||
1095 c->tty_path) {
1096
1097 x = strdup(default_term_for_tty(tty_path(c)));
1098 if (!x)
1099 return -ENOMEM;
1100 our_env[n_env++] = x;
1101 }
1102
1103 our_env[n_env++] = NULL;
09812eb7 1104 assert(n_env <= 10);
7cae38c4
LP
1105
1106 *ret = our_env;
1107 our_env = NULL;
1108
1109 return 0;
1110}
1111
9fb86720 1112int exec_spawn(ExecCommand *command,
9e2f7c11 1113 char **argv,
c17ec25e 1114 ExecContext *context,
c2748801 1115 int fds[], unsigned n_fds,
1137a57c 1116 char **environment,
81a2b7ce
LP
1117 bool apply_permissions,
1118 bool apply_chroot,
1e3ad081 1119 bool apply_tty_stdin,
80876c20 1120 bool confirm_spawn,
13b84ec7 1121 CGroupControllerMask cgroup_supported,
4ad49000 1122 const char *cgroup_path,
62bca2c6 1123 const char *unit_id,
09812eb7 1124 usec_t watchdog_usec,
31a7eb86 1125 int idle_pipe[4],
613b411c 1126 ExecRuntime *runtime,
81a2b7ce
LP
1127 pid_t *ret) {
1128
4ad49000
LP
1129 _cleanup_strv_free_ char **files_env = NULL;
1130 int socket_fd;
1131 char *line;
034c6ed7 1132 pid_t pid;
8e274523 1133 int r;
034c6ed7 1134
5cb5a6ff
LP
1135 assert(command);
1136 assert(context);
1137 assert(ret);
034c6ed7
LP
1138 assert(fds || n_fds <= 0);
1139
4f2d528d
LP
1140 if (context->std_input == EXEC_INPUT_SOCKET ||
1141 context->std_output == EXEC_OUTPUT_SOCKET ||
1142 context->std_error == EXEC_OUTPUT_SOCKET) {
1143
1144 if (n_fds != 1)
1145 return -EINVAL;
1146
1147 socket_fd = fds[0];
1148
1149 fds = NULL;
1150 n_fds = 0;
1151 } else
1152 socket_fd = -1;
1153
b66871da
ZJS
1154 r = exec_context_load_environment(context, &files_env);
1155 if (r < 0) {
bbc9006e
MT
1156 log_struct_unit(LOG_ERR,
1157 unit_id,
23635a85
ZJS
1158 "MESSAGE=Failed to load environment files: %s", strerror(-r),
1159 "ERRNO=%d", -r,
1160 NULL);
8c7be95e
LP
1161 return r;
1162 }
1163
9e2f7c11
LP
1164 if (!argv)
1165 argv = command->argv;
1166
af6da548 1167 line = exec_command_line(argv);
b66871da
ZJS
1168 if (!line)
1169 return log_oom();
1a63a750 1170
bbc9006e 1171 log_struct_unit(LOG_DEBUG,
099a804b
LP
1172 unit_id,
1173 "EXECUTABLE=%s", command->path,
1174 "MESSAGE=About to execute: %s", line,
1175 NULL);
1a63a750 1176 free(line);
acbb0225 1177
b66871da
ZJS
1178 pid = fork();
1179 if (pid < 0)
1180 return -errno;
034c6ed7
LP
1181
1182 if (pid == 0) {
613b411c 1183 _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
59fccd82 1184 const char *username = NULL, *home = NULL, *shell = NULL;
7cae38c4 1185 unsigned n_dont_close = 0;
613b411c 1186 int dont_close[n_fds + 3];
81a2b7ce
LP
1187 uid_t uid = (uid_t) -1;
1188 gid_t gid = (gid_t) -1;
613b411c
LP
1189 sigset_t ss;
1190 int i, err;
309bff19 1191
034c6ed7 1192 /* child */
5cb5a6ff 1193
5d6b1584 1194 rename_process_from_path(command->path);
5b6319dc 1195
1b91d3e8
LP
1196 /* We reset exactly these signals, since they are the
1197 * only ones we set to SIG_IGN in the main daemon. All
1198 * others we leave untouched because we set them to
1199 * SIG_DFL or a valid handler initially, both of which
1200 * will be demoted to SIG_DFL. */
1201 default_signals(SIGNALS_CRASH_HANDLER,
9a34ec5f 1202 SIGNALS_IGNORE, -1);
7b683879 1203
353e12c2
LP
1204 if (context->ignore_sigpipe)
1205 ignore_signals(SIGPIPE, -1);
1206
1207 assert_se(sigemptyset(&ss) == 0);
1208 if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) {
4c2630eb 1209 err = -errno;
309bff19 1210 r = EXIT_SIGNAL_MASK;
8c7be95e 1211 goto fail_child;
309bff19
LP
1212 }
1213
31a7eb86
ZJS
1214 if (idle_pipe)
1215 do_idle_pipe_dance(idle_pipe);
f2b68789 1216
85d73053
LP
1217 /* Close sockets very early to make sure we don't
1218 * block init reexecution because it cannot bind its
1219 * sockets */
4d8a7798 1220 log_forget_fds();
613b411c
LP
1221
1222 if (socket_fd >= 0)
1223 dont_close[n_dont_close++] = socket_fd;
1224 if (n_fds > 0) {
1225 memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
1226 n_dont_close += n_fds;
1227 }
1228 if (runtime) {
1229 if (runtime->netns_storage_socket[0] >= 0)
1230 dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
1231 if (runtime->netns_storage_socket[1] >= 0)
1232 dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
1233 }
1234
1235 err = close_all_fds(dont_close, n_dont_close);
4c2630eb 1236 if (err < 0) {
fc9b2a84 1237 r = EXIT_FDS;
8c7be95e 1238 goto fail_child;
fc9b2a84
LP
1239 }
1240
74922904 1241 if (!context->same_pgrp)
8d567588 1242 if (setsid() < 0) {
4c2630eb 1243 err = -errno;
8d567588 1244 r = EXIT_SETSID;
8c7be95e 1245 goto fail_child;
8d567588 1246 }
80876c20 1247
c5da34ef
LP
1248 if (context->tcpwrap_name) {
1249 if (socket_fd >= 0)
1250 if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) {
4c2630eb 1251 err = -EACCES;
c5da34ef 1252 r = EXIT_TCPWRAP;
8c7be95e 1253 goto fail_child;
c5da34ef
LP
1254 }
1255
1256 for (i = 0; i < (int) n_fds; i++) {
1257 if (!socket_tcpwrap(fds[i], context->tcpwrap_name)) {
4c2630eb 1258 err = -EACCES;
c5da34ef 1259 r = EXIT_TCPWRAP;
8c7be95e 1260 goto fail_child;
c5da34ef 1261 }
df1f0afe 1262 }
c5da34ef 1263 }
df1f0afe 1264
6ea832a2
LP
1265 exec_context_tty_reset(context);
1266
af6da548 1267 if (confirm_spawn) {
80876c20
LP
1268 char response;
1269
af6da548
LP
1270 err = ask_for_confirmation(&response, argv);
1271 if (err == -ETIMEDOUT)
1272 write_confirm_message("Confirmation question timed out, assuming positive response.\n");
1273 else if (err < 0)
1274 write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-err));
1275 else if (response == 's') {
1276 write_confirm_message("Skipping execution.\n");
4c2630eb 1277 err = -ECANCELED;
80876c20 1278 r = EXIT_CONFIRM;
8c7be95e 1279 goto fail_child;
af6da548
LP
1280 } else if (response == 'n') {
1281 write_confirm_message("Failing execution.\n");
4c2630eb 1282 err = r = 0;
8c7be95e 1283 goto fail_child;
ee2b4894 1284 }
034c6ed7
LP
1285 }
1286
da726a4d
LP
1287 /* If a socket is connected to STDIN/STDOUT/STDERR, we
1288 * must sure to drop O_NONBLOCK */
1289 if (socket_fd >= 0)
1290 fd_nonblock(socket_fd, false);
1291
af6da548
LP
1292 err = setup_input(context, socket_fd, apply_tty_stdin);
1293 if (err < 0) {
1294 r = EXIT_STDIN;
1295 goto fail_child;
4c2630eb 1296 }
9eba9da4 1297
2b6bf07d 1298 err = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), unit_id, apply_tty_stdin);
af6da548
LP
1299 if (err < 0) {
1300 r = EXIT_STDOUT;
1301 goto fail_child;
4c2630eb 1302 }
94f04347 1303
2b6bf07d 1304 err = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), unit_id, apply_tty_stdin);
4c2630eb 1305 if (err < 0) {
80876c20 1306 r = EXIT_STDERR;
8c7be95e 1307 goto fail_child;
071830ff
LP
1308 }
1309
4ad49000 1310 if (cgroup_path) {
13b84ec7 1311 err = cg_attach_everywhere(cgroup_supported, cgroup_path, 0);
4c2630eb 1312 if (err < 0) {
8e274523 1313 r = EXIT_CGROUP;
8c7be95e 1314 goto fail_child;
8e274523 1315 }
4c2630eb 1316 }
8e274523 1317
dd6c17b1 1318 if (context->oom_score_adjust_set) {
fb33a393 1319 char t[16];
034c6ed7 1320
dd6c17b1 1321 snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
fb33a393 1322 char_array_0(t);
034c6ed7 1323
574d5f2d 1324 if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
8600c525
KS
1325 err = -errno;
1326 r = EXIT_OOM_ADJUST;
1327 goto fail_child;
fb33a393 1328 }
034c6ed7
LP
1329 }
1330
fb33a393
LP
1331 if (context->nice_set)
1332 if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
4c2630eb 1333 err = -errno;
fb33a393 1334 r = EXIT_NICE;
8c7be95e 1335 goto fail_child;
fb33a393
LP
1336 }
1337
94f04347 1338 if (context->cpu_sched_set) {
b92bea5d
ZJS
1339 struct sched_param param = {
1340 .sched_priority = context->cpu_sched_priority,
1341 };
94f04347 1342
e62d8c39
ZJS
1343 r = sched_setscheduler(0,
1344 context->cpu_sched_policy |
1345 (context->cpu_sched_reset_on_fork ?
1346 SCHED_RESET_ON_FORK : 0),
1347 &param);
1348 if (r < 0) {
4c2630eb 1349 err = -errno;
94f04347 1350 r = EXIT_SETSCHEDULER;
8c7be95e 1351 goto fail_child;
94f04347
LP
1352 }
1353 }
1354
82c121a4
LP
1355 if (context->cpuset)
1356 if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
4c2630eb 1357 err = -errno;
94f04347 1358 r = EXIT_CPUAFFINITY;
8c7be95e 1359 goto fail_child;
94f04347
LP
1360 }
1361
9eba9da4
LP
1362 if (context->ioprio_set)
1363 if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
4c2630eb 1364 err = -errno;
9eba9da4 1365 r = EXIT_IOPRIO;
8c7be95e 1366 goto fail_child;
9eba9da4
LP
1367 }
1368
d88a251b 1369 if (context->timer_slack_nsec != (nsec_t) -1)
03fae018 1370 if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
4c2630eb 1371 err = -errno;
94f04347 1372 r = EXIT_TIMERSLACK;
8c7be95e 1373 goto fail_child;
94f04347
LP
1374 }
1375
ac45f971
LP
1376 if (context->personality != 0xffffffffUL)
1377 if (personality(context->personality) < 0) {
1378 err = -errno;
1379 r = EXIT_PERSONALITY;
1380 goto fail_child;
1381 }
1382
169c1bda 1383 if (context->utmp_id)
0ad26e09 1384 utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path);
169c1bda 1385
81a2b7ce
LP
1386 if (context->user) {
1387 username = context->user;
59fccd82 1388 err = get_user_creds(&username, &uid, &gid, &home, &shell);
4c2630eb 1389 if (err < 0) {
81a2b7ce 1390 r = EXIT_USER;
8c7be95e 1391 goto fail_child;
81a2b7ce 1392 }
d8b4e2e9 1393
4c2630eb
MS
1394 if (is_terminal_input(context->std_input)) {
1395 err = chown_terminal(STDIN_FILENO, uid);
1396 if (err < 0) {
d8b4e2e9 1397 r = EXIT_STDIN;
8c7be95e 1398 goto fail_child;
d8b4e2e9 1399 }
4c2630eb 1400 }
81a2b7ce
LP
1401 }
1402
8aa75193
LP
1403#ifdef HAVE_PAM
1404 if (cgroup_path && context->user && context->pam_name) {
1405 err = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, 0644, uid, gid);
1406 if (err < 0) {
1407 r = EXIT_CGROUP;
1408 goto fail_child;
1409 }
1410
1411
1412 err = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, 0755, uid, gid);
1413 if (err < 0) {
1414 r = EXIT_CGROUP;
1415 goto fail_child;
1416 }
1417 }
1418#endif
1419
4c2630eb
MS
1420 if (apply_permissions) {
1421 err = enforce_groups(context, username, gid);
1422 if (err < 0) {
3b8bddde
LP
1423 r = EXIT_GROUP;
1424 goto fail_child;
1425 }
4c2630eb 1426 }
3b8bddde
LP
1427
1428 umask(context->umask);
1429
5b6319dc 1430#ifdef HAVE_PAM
b7848021 1431 if (apply_permissions && context->pam_name && username) {
940c5210 1432 err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
4c2630eb 1433 if (err < 0) {
5b6319dc 1434 r = EXIT_PAM;
8c7be95e 1435 goto fail_child;
5b6319dc
LP
1436 }
1437 }
1438#endif
613b411c
LP
1439 if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) {
1440 err = setup_netns(runtime->netns_storage_socket);
1441 if (err < 0) {
ff01d048
LP
1442 r = EXIT_NETWORK;
1443 goto fail_child;
1444 }
ff01d048 1445 }
5b6319dc 1446
613b411c
LP
1447 if (!strv_isempty(context->read_write_dirs) ||
1448 !strv_isempty(context->read_only_dirs) ||
1449 !strv_isempty(context->inaccessible_dirs) ||
ac0930c8 1450 context->mount_flags != 0 ||
7f112f50
LP
1451 (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir)) ||
1452 context->private_devices) {
613b411c
LP
1453
1454 char *tmp = NULL, *var = NULL;
1455
1456 /* The runtime struct only contains the parent
1457 * of the private /tmp, which is
1458 * non-accessible to world users. Inside of it
1459 * there's a /tmp that is sticky, and that's
1460 * the one we want to use here. */
1461
1462 if (context->private_tmp && runtime) {
1463 if (runtime->tmp_dir)
1464 tmp = strappenda(runtime->tmp_dir, "/tmp");
1465 if (runtime->var_tmp_dir)
1466 var = strappenda(runtime->var_tmp_dir, "/tmp");
1467 }
1468
1469 err = setup_namespace(
1470 context->read_write_dirs,
1471 context->read_only_dirs,
1472 context->inaccessible_dirs,
1473 tmp,
1474 var,
7f112f50 1475 context->private_devices,
613b411c
LP
1476 context->mount_flags);
1477
4c2630eb
MS
1478 if (err < 0) {
1479 r = EXIT_NAMESPACE;
8c7be95e 1480 goto fail_child;
4c2630eb
MS
1481 }
1482 }
04aa0cb9 1483
81a2b7ce
LP
1484 if (apply_chroot) {
1485 if (context->root_directory)
1486 if (chroot(context->root_directory) < 0) {
4c2630eb 1487 err = -errno;
81a2b7ce 1488 r = EXIT_CHROOT;
8c7be95e 1489 goto fail_child;
81a2b7ce
LP
1490 }
1491
1492 if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
4c2630eb 1493 err = -errno;
81a2b7ce 1494 r = EXIT_CHDIR;
8c7be95e 1495 goto fail_child;
81a2b7ce
LP
1496 }
1497 } else {
7fd1b19b 1498 _cleanup_free_ char *d = NULL;
81a2b7ce
LP
1499
1500 if (asprintf(&d, "%s/%s",
1501 context->root_directory ? context->root_directory : "",
1502 context->working_directory ? context->working_directory : "") < 0) {
4c2630eb 1503 err = -ENOMEM;
81a2b7ce 1504 r = EXIT_MEMORY;
8c7be95e 1505 goto fail_child;
81a2b7ce
LP
1506 }
1507
1508 if (chdir(d) < 0) {
4c2630eb 1509 err = -errno;
81a2b7ce 1510 r = EXIT_CHDIR;
8c7be95e 1511 goto fail_child;
81a2b7ce 1512 }
81a2b7ce
LP
1513 }
1514
fc9b2a84
LP
1515 /* We repeat the fd closing here, to make sure that
1516 * nothing is leaked from the PAM modules */
4c2630eb
MS
1517 err = close_all_fds(fds, n_fds);
1518 if (err >= 0)
1519 err = shift_fds(fds, n_fds);
1520 if (err >= 0)
1521 err = flags_fds(fds, n_fds, context->non_blocking);
1522 if (err < 0) {
034c6ed7 1523 r = EXIT_FDS;
8c7be95e 1524 goto fail_child;
034c6ed7
LP
1525 }
1526
81a2b7ce 1527 if (apply_permissions) {
034c6ed7 1528
81a2b7ce
LP
1529 for (i = 0; i < RLIMIT_NLIMITS; i++) {
1530 if (!context->rlimit[i])
1531 continue;
1532
68faf98c 1533 if (setrlimit_closest(i, context->rlimit[i]) < 0) {
4c2630eb 1534 err = -errno;
81a2b7ce 1535 r = EXIT_LIMITS;
8c7be95e 1536 goto fail_child;
81a2b7ce 1537 }
034c6ed7 1538 }
034c6ed7 1539
4c2630eb 1540 if (context->capability_bounding_set_drop) {
ec8927ca 1541 err = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
4c2630eb 1542 if (err < 0) {
73090dc8
LP
1543 r = EXIT_CAPABILITIES;
1544 goto fail_child;
1545 }
4c2630eb 1546 }
260abb78 1547
4c2630eb
MS
1548 if (context->user) {
1549 err = enforce_user(context, uid);
1550 if (err < 0) {
81a2b7ce 1551 r = EXIT_USER;
8c7be95e 1552 goto fail_child;
81a2b7ce 1553 }
4c2630eb 1554 }
81a2b7ce 1555
35b8ca3a 1556 /* PR_GET_SECUREBITS is not privileged, while
693ced48
LP
1557 * PR_SET_SECUREBITS is. So to suppress
1558 * potential EPERMs we'll try not to call
1559 * PR_SET_SECUREBITS unless necessary. */
1560 if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
1561 if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
4c2630eb 1562 err = -errno;
693ced48 1563 r = EXIT_SECUREBITS;
8c7be95e 1564 goto fail_child;
693ced48 1565 }
81a2b7ce
LP
1566
1567 if (context->capabilities)
1568 if (cap_set_proc(context->capabilities) < 0) {
4c2630eb 1569 err = -errno;
81a2b7ce 1570 r = EXIT_CAPABILITIES;
8c7be95e 1571 goto fail_child;
81a2b7ce 1572 }
8351ceae
LP
1573
1574 if (context->no_new_privileges)
1575 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
1576 err = -errno;
1577 r = EXIT_NO_NEW_PRIVILEGES;
1578 goto fail_child;
1579 }
1580
c0467cf3 1581#ifdef HAVE_SECCOMP
57183d11 1582 if (context->syscall_filter || context->syscall_archs) {
c0467cf3 1583 err = apply_seccomp(context);
8351ceae
LP
1584 if (err < 0) {
1585 r = EXIT_SECCOMP;
1586 goto fail_child;
1587 }
1588 }
c0467cf3 1589#endif
17df7223 1590
7b52a628 1591#ifdef HAVE_SELINUX
5c56a259 1592 if (context->selinux_context && use_selinux()) {
5f8640fb
LP
1593 err = setexeccon(context->selinux_context);
1594 if (err < 0 && !context->selinux_context_ignore) {
7b52a628
MS
1595 r = EXIT_SELINUX_CONTEXT;
1596 goto fail_child;
1597 }
1598 }
1599#endif
94f04347
LP
1600 }
1601
09812eb7 1602 err = build_environment(context, n_fds, watchdog_usec, home, username, shell, &our_env);
7cae38c4 1603 if (r < 0) {
81a2b7ce 1604 r = EXIT_MEMORY;
8c7be95e 1605 goto fail_child;
81a2b7ce 1606 }
034c6ed7 1607
e62d8c39
ZJS
1608 final_env = strv_env_merge(5,
1609 environment,
1610 our_env,
1611 context->environment,
1612 files_env,
1613 pam_env,
1614 NULL);
1615 if (!final_env) {
4c2630eb 1616 err = -ENOMEM;
81a2b7ce 1617 r = EXIT_MEMORY;
8c7be95e 1618 goto fail_child;
81a2b7ce 1619 }
034c6ed7 1620
e62d8c39
ZJS
1621 final_argv = replace_env_argv(argv, final_env);
1622 if (!final_argv) {
4c2630eb 1623 err = -ENOMEM;
fab56fc5 1624 r = EXIT_MEMORY;
8c7be95e 1625 goto fail_child;
fab56fc5
LP
1626 }
1627
a6ff950e
LP
1628 final_env = strv_env_clean(final_env);
1629
03bb799e
HH
1630 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1631 line = exec_command_line(final_argv);
1632 if (line) {
1633 log_open();
1634 log_struct_unit(LOG_DEBUG,
1635 unit_id,
1636 "EXECUTABLE=%s", command->path,
099a804b
LP
1637 "MESSAGE=Executing: %s", line,
1638 NULL);
03bb799e
HH
1639 log_close();
1640 free(line);
1641 line = NULL;
1642 }
1643 }
fab56fc5 1644 execve(command->path, final_argv, final_env);
4c2630eb 1645 err = -errno;
034c6ed7
LP
1646 r = EXIT_EXEC;
1647
8c7be95e 1648 fail_child:
4c2630eb
MS
1649 if (r != 0) {
1650 log_open();
23635a85
ZJS
1651 log_struct(LOG_ERR, MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
1652 "EXECUTABLE=%s", command->path,
1653 "MESSAGE=Failed at step %s spawning %s: %s",
1654 exit_status_to_string(r, EXIT_STATUS_SYSTEMD),
1655 command->path, strerror(-err),
1656 "ERRNO=%d", -err,
1657 NULL);
1658 log_close();
4c2630eb
MS
1659 }
1660
034c6ed7
LP
1661 _exit(r);
1662 }
1663
bbc9006e 1664 log_struct_unit(LOG_DEBUG,
e62d8c39 1665 unit_id,
ccd06097
ZJS
1666 "MESSAGE=Forked %s as "PID_FMT,
1667 command->path, pid,
e62d8c39 1668 NULL);
23635a85 1669
80876c20
LP
1670 /* We add the new process to the cgroup both in the child (so
1671 * that we can be sure that no user code is ever executed
1672 * outside of the cgroup) and in the parent (so that we can be
1673 * sure that when we kill the cgroup the process will be
1674 * killed too). */
4ad49000
LP
1675 if (cgroup_path)
1676 cg_attach(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, pid);
2da3263a 1677
b58b4116 1678 exec_status_start(&command->exec_status, pid);
9fb86720 1679
034c6ed7 1680 *ret = pid;
5cb5a6ff
LP
1681 return 0;
1682}
1683
034c6ed7
LP
1684void exec_context_init(ExecContext *c) {
1685 assert(c);
1686
4c12626c 1687 c->umask = 0022;
9eba9da4 1688 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
94f04347 1689 c->cpu_sched_policy = SCHED_OTHER;
071830ff 1690 c->syslog_priority = LOG_DAEMON|LOG_INFO;
74922904 1691 c->syslog_level_prefix = true;
353e12c2 1692 c->ignore_sigpipe = true;
d88a251b 1693 c->timer_slack_nsec = (nsec_t) -1;
ac45f971 1694 c->personality = 0xffffffffUL;
034c6ed7
LP
1695}
1696
613b411c 1697void exec_context_done(ExecContext *c) {
5cb5a6ff
LP
1698 unsigned l;
1699
1700 assert(c);
1701
1702 strv_free(c->environment);
034c6ed7 1703 c->environment = NULL;
5cb5a6ff 1704
8c7be95e
LP
1705 strv_free(c->environment_files);
1706 c->environment_files = NULL;
1707
034c6ed7 1708 for (l = 0; l < ELEMENTSOF(c->rlimit); l++) {
5cb5a6ff 1709 free(c->rlimit[l]);
034c6ed7
LP
1710 c->rlimit[l] = NULL;
1711 }
1712
9eba9da4
LP
1713 free(c->working_directory);
1714 c->working_directory = NULL;
1715 free(c->root_directory);
1716 c->root_directory = NULL;
5cb5a6ff 1717
80876c20
LP
1718 free(c->tty_path);
1719 c->tty_path = NULL;
1720
df1f0afe
LP
1721 free(c->tcpwrap_name);
1722 c->tcpwrap_name = NULL;
1723
071830ff
LP
1724 free(c->syslog_identifier);
1725 c->syslog_identifier = NULL;
1726
5cb5a6ff 1727 free(c->user);
034c6ed7
LP
1728 c->user = NULL;
1729
5cb5a6ff 1730 free(c->group);
034c6ed7
LP
1731 c->group = NULL;
1732
1733 strv_free(c->supplementary_groups);
1734 c->supplementary_groups = NULL;
94f04347 1735
5b6319dc
LP
1736 free(c->pam_name);
1737 c->pam_name = NULL;
1738
94f04347
LP
1739 if (c->capabilities) {
1740 cap_free(c->capabilities);
1741 c->capabilities = NULL;
1742 }
15ae422b
LP
1743
1744 strv_free(c->read_only_dirs);
1745 c->read_only_dirs = NULL;
1746
1747 strv_free(c->read_write_dirs);
1748 c->read_write_dirs = NULL;
1749
1750 strv_free(c->inaccessible_dirs);
1751 c->inaccessible_dirs = NULL;
82c121a4
LP
1752
1753 if (c->cpuset)
1754 CPU_FREE(c->cpuset);
86a3475b
LP
1755
1756 free(c->utmp_id);
1757 c->utmp_id = NULL;
b9a0e010 1758
7b52a628
MS
1759 free(c->selinux_context);
1760 c->selinux_context = NULL;
1761
c0467cf3 1762#ifdef HAVE_SECCOMP
17df7223
LP
1763 set_free(c->syscall_filter);
1764 c->syscall_filter = NULL;
57183d11
LP
1765
1766 set_free(c->syscall_archs);
1767 c->syscall_archs = NULL;
c0467cf3 1768#endif
5cb5a6ff
LP
1769}
1770
43d0fcbd
LP
1771void exec_command_done(ExecCommand *c) {
1772 assert(c);
1773
1774 free(c->path);
1775 c->path = NULL;
1776
1777 strv_free(c->argv);
1778 c->argv = NULL;
1779}
1780
1781void exec_command_done_array(ExecCommand *c, unsigned n) {
1782 unsigned i;
1783
1784 for (i = 0; i < n; i++)
1785 exec_command_done(c+i);
1786}
1787
5cb5a6ff
LP
1788void exec_command_free_list(ExecCommand *c) {
1789 ExecCommand *i;
1790
1791 while ((i = c)) {
71fda00f 1792 LIST_REMOVE(command, c, i);
43d0fcbd 1793 exec_command_done(i);
5cb5a6ff
LP
1794 free(i);
1795 }
1796}
1797
034c6ed7
LP
1798void exec_command_free_array(ExecCommand **c, unsigned n) {
1799 unsigned i;
1800
1801 for (i = 0; i < n; i++) {
1802 exec_command_free_list(c[i]);
1803 c[i] = NULL;
1804 }
1805}
1806
8c7be95e
LP
1807int exec_context_load_environment(const ExecContext *c, char ***l) {
1808 char **i, **r = NULL;
1809
1810 assert(c);
1811 assert(l);
1812
1813 STRV_FOREACH(i, c->environment_files) {
1814 char *fn;
1815 int k;
1816 bool ignore = false;
1817 char **p;
7fd1b19b 1818 _cleanup_globfree_ glob_t pglob = {};
2bef10ab 1819 int count, n;
8c7be95e
LP
1820
1821 fn = *i;
1822
1823 if (fn[0] == '-') {
1824 ignore = true;
1825 fn ++;
1826 }
1827
1828 if (!path_is_absolute(fn)) {
8c7be95e
LP
1829 if (ignore)
1830 continue;
1831
1832 strv_free(r);
1833 return -EINVAL;
1834 }
1835
2bef10ab 1836 /* Filename supports globbing, take all matching files */
2bef10ab
PL
1837 errno = 0;
1838 if (glob(fn, 0, NULL, &pglob) != 0) {
2bef10ab
PL
1839 if (ignore)
1840 continue;
8c7be95e 1841
2bef10ab
PL
1842 strv_free(r);
1843 return errno ? -errno : -EINVAL;
1844 }
1845 count = pglob.gl_pathc;
1846 if (count == 0) {
8c7be95e
LP
1847 if (ignore)
1848 continue;
1849
1850 strv_free(r);
2bef10ab 1851 return -EINVAL;
8c7be95e 1852 }
2bef10ab 1853 for (n = 0; n < count; n++) {
f73141d7 1854 k = load_env_file(pglob.gl_pathv[n], NULL, &p);
2bef10ab
PL
1855 if (k < 0) {
1856 if (ignore)
1857 continue;
8c7be95e 1858
2bef10ab 1859 strv_free(r);
2bef10ab 1860 return k;
e9c1ea9d 1861 }
ebc05a09 1862 /* Log invalid environment variables with filename */
e9c1ea9d
JSJ
1863 if (p)
1864 p = strv_env_clean_log(p, pglob.gl_pathv[n]);
8c7be95e 1865
2bef10ab
PL
1866 if (r == NULL)
1867 r = p;
1868 else {
1869 char **m;
8c7be95e 1870
2bef10ab
PL
1871 m = strv_env_merge(2, r, p);
1872 strv_free(r);
1873 strv_free(p);
c84a9488 1874 if (!m)
2bef10ab 1875 return -ENOMEM;
2bef10ab
PL
1876
1877 r = m;
1878 }
8c7be95e
LP
1879 }
1880 }
1881
1882 *l = r;
1883
1884 return 0;
1885}
1886
6ac8fdc9
MS
1887static bool tty_may_match_dev_console(const char *tty) {
1888 char *active = NULL, *console;
1889 bool b;
1890
1891 if (startswith(tty, "/dev/"))
1892 tty += 5;
1893
1894 /* trivial identity? */
1895 if (streq(tty, "console"))
1896 return true;
1897
1898 console = resolve_dev_console(&active);
1899 /* if we could not resolve, assume it may */
1900 if (!console)
1901 return true;
1902
1903 /* "tty0" means the active VC, so it may be the same sometimes */
1904 b = streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty));
1905 free(active);
1906
1907 return b;
1908}
1909
1910bool exec_context_may_touch_console(ExecContext *ec) {
1911 return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate ||
1912 is_terminal_input(ec->std_input) ||
1913 is_terminal_output(ec->std_output) ||
1914 is_terminal_output(ec->std_error)) &&
1915 tty_may_match_dev_console(tty_path(ec));
1916}
1917
15ae422b
LP
1918static void strv_fprintf(FILE *f, char **l) {
1919 char **g;
1920
1921 assert(f);
1922
1923 STRV_FOREACH(g, l)
1924 fprintf(f, " %s", *g);
1925}
1926
5cb5a6ff 1927void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
507f22bd 1928 char **e;
94f04347 1929 unsigned i;
9eba9da4 1930
5cb5a6ff
LP
1931 assert(c);
1932 assert(f);
1933
4ad49000 1934 prefix = strempty(prefix);
5cb5a6ff
LP
1935
1936 fprintf(f,
94f04347
LP
1937 "%sUMask: %04o\n"
1938 "%sWorkingDirectory: %s\n"
451a074f 1939 "%sRootDirectory: %s\n"
15ae422b 1940 "%sNonBlocking: %s\n"
64747e2d 1941 "%sPrivateTmp: %s\n"
4819ff03 1942 "%sPrivateNetwork: %s\n"
7f112f50 1943 "%sPrivateDevices: %s\n"
4819ff03 1944 "%sIgnoreSIGPIPE: %s\n",
5cb5a6ff 1945 prefix, c->umask,
9eba9da4 1946 prefix, c->working_directory ? c->working_directory : "/",
451a074f 1947 prefix, c->root_directory ? c->root_directory : "/",
15ae422b 1948 prefix, yes_no(c->non_blocking),
64747e2d 1949 prefix, yes_no(c->private_tmp),
4819ff03 1950 prefix, yes_no(c->private_network),
7f112f50 1951 prefix, yes_no(c->private_devices),
4819ff03 1952 prefix, yes_no(c->ignore_sigpipe));
fb33a393 1953
8c7be95e
LP
1954 STRV_FOREACH(e, c->environment)
1955 fprintf(f, "%sEnvironment: %s\n", prefix, *e);
1956
1957 STRV_FOREACH(e, c->environment_files)
1958 fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
94f04347 1959
df1f0afe
LP
1960 if (c->tcpwrap_name)
1961 fprintf(f,
1962 "%sTCPWrapName: %s\n",
1963 prefix, c->tcpwrap_name);
1964
fb33a393
LP
1965 if (c->nice_set)
1966 fprintf(f,
1967 "%sNice: %i\n",
1968 prefix, c->nice);
1969
dd6c17b1 1970 if (c->oom_score_adjust_set)
fb33a393 1971 fprintf(f,
dd6c17b1
LP
1972 "%sOOMScoreAdjust: %i\n",
1973 prefix, c->oom_score_adjust);
9eba9da4 1974
94f04347
LP
1975 for (i = 0; i < RLIM_NLIMITS; i++)
1976 if (c->rlimit[i])
ea430986 1977 fprintf(f, "%s%s: %llu\n", prefix, rlimit_to_string(i), (unsigned long long) c->rlimit[i]->rlim_max);
94f04347 1978
f8b69d1d
MS
1979 if (c->ioprio_set) {
1980 char *class_str;
1981 int r;
1982
1983 r = ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
1984 if (r < 0)
1985 class_str = NULL;
9eba9da4
LP
1986 fprintf(f,
1987 "%sIOSchedulingClass: %s\n"
1988 "%sIOPriority: %i\n",
f8b69d1d 1989 prefix, strna(class_str),
9eba9da4 1990 prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
f8b69d1d
MS
1991 free(class_str);
1992 }
94f04347 1993
f8b69d1d
MS
1994 if (c->cpu_sched_set) {
1995 char *policy_str;
1996 int r;
1997
1998 r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
1999 if (r < 0)
2000 policy_str = NULL;
94f04347
LP
2001 fprintf(f,
2002 "%sCPUSchedulingPolicy: %s\n"
38b48754
LP
2003 "%sCPUSchedulingPriority: %i\n"
2004 "%sCPUSchedulingResetOnFork: %s\n",
f8b69d1d 2005 prefix, strna(policy_str),
38b48754
LP
2006 prefix, c->cpu_sched_priority,
2007 prefix, yes_no(c->cpu_sched_reset_on_fork));
f8b69d1d 2008 free(policy_str);
b929bf04 2009 }
94f04347 2010
82c121a4 2011 if (c->cpuset) {
94f04347 2012 fprintf(f, "%sCPUAffinity:", prefix);
82c121a4
LP
2013 for (i = 0; i < c->cpuset_ncpus; i++)
2014 if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
43a99a7a 2015 fprintf(f, " %u", i);
94f04347
LP
2016 fputs("\n", f);
2017 }
2018
d88a251b 2019 if (c->timer_slack_nsec != (nsec_t) -1)
ccd06097 2020 fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, c->timer_slack_nsec);
94f04347
LP
2021
2022 fprintf(f,
80876c20
LP
2023 "%sStandardInput: %s\n"
2024 "%sStandardOutput: %s\n"
2025 "%sStandardError: %s\n",
2026 prefix, exec_input_to_string(c->std_input),
2027 prefix, exec_output_to_string(c->std_output),
2028 prefix, exec_output_to_string(c->std_error));
2029
2030 if (c->tty_path)
2031 fprintf(f,
6ea832a2
LP
2032 "%sTTYPath: %s\n"
2033 "%sTTYReset: %s\n"
2034 "%sTTYVHangup: %s\n"
2035 "%sTTYVTDisallocate: %s\n",
2036 prefix, c->tty_path,
2037 prefix, yes_no(c->tty_reset),
2038 prefix, yes_no(c->tty_vhangup),
2039 prefix, yes_no(c->tty_vt_disallocate));
94f04347 2040
5ce70e5b
ZJS
2041 if (c->std_output == EXEC_OUTPUT_SYSLOG ||
2042 c->std_output == EXEC_OUTPUT_KMSG ||
2043 c->std_output == EXEC_OUTPUT_JOURNAL ||
2044 c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
2045 c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
2046 c->std_output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE ||
2047 c->std_error == EXEC_OUTPUT_SYSLOG ||
2048 c->std_error == EXEC_OUTPUT_KMSG ||
2049 c->std_error == EXEC_OUTPUT_JOURNAL ||
2050 c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
2051 c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
2052 c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE) {
f8b69d1d 2053
5ce70e5b 2054 _cleanup_free_ char *fac_str = NULL, *lvl_str = NULL;
f8b69d1d 2055
5ce70e5b
ZJS
2056 log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
2057 log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
f8b69d1d 2058
94f04347
LP
2059 fprintf(f,
2060 "%sSyslogFacility: %s\n"
2061 "%sSyslogLevel: %s\n",
f8b69d1d
MS
2062 prefix, strna(fac_str),
2063 prefix, strna(lvl_str));
f8b69d1d 2064 }
94f04347
LP
2065
2066 if (c->capabilities) {
5ce70e5b
ZJS
2067 _cleanup_cap_free_charp_ char *t;
2068
2069 t = cap_to_text(c->capabilities, NULL);
2070 if (t)
2071 fprintf(f, "%sCapabilities: %s\n", prefix, t);
94f04347
LP
2072 }
2073
2074 if (c->secure_bits)
2075 fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
2076 prefix,
cbb21cca
ZJS
2077 (c->secure_bits & 1<<SECURE_KEEP_CAPS) ? " keep-caps" : "",
2078 (c->secure_bits & 1<<SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
2079 (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
2080 (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
2081 (c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
2082 (c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
94f04347
LP
2083
2084 if (c->capability_bounding_set_drop) {
ae556c21 2085 unsigned long l;
260abb78 2086 fprintf(f, "%sCapabilityBoundingSet:", prefix);
94f04347 2087
64685e0c 2088 for (l = 0; l <= cap_last_cap(); l++)
ae556c21 2089 if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l))) {
5ce70e5b 2090 _cleanup_cap_free_charp_ char *t;
94f04347 2091
5ce70e5b
ZJS
2092 t = cap_to_name(l);
2093 if (t)
94f04347 2094 fprintf(f, " %s", t);
94f04347
LP
2095 }
2096
2097 fputs("\n", f);
2098 }
2099
2100 if (c->user)
f2d3769a 2101 fprintf(f, "%sUser: %s\n", prefix, c->user);
94f04347 2102 if (c->group)
f2d3769a 2103 fprintf(f, "%sGroup: %s\n", prefix, c->group);
94f04347 2104
15ae422b 2105 if (strv_length(c->supplementary_groups) > 0) {
94f04347 2106 fprintf(f, "%sSupplementaryGroups:", prefix);
15ae422b
LP
2107 strv_fprintf(f, c->supplementary_groups);
2108 fputs("\n", f);
2109 }
94f04347 2110
5b6319dc 2111 if (c->pam_name)
f2d3769a 2112 fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
5b6319dc 2113
15ae422b
LP
2114 if (strv_length(c->read_write_dirs) > 0) {
2115 fprintf(f, "%sReadWriteDirs:", prefix);
2116 strv_fprintf(f, c->read_write_dirs);
2117 fputs("\n", f);
2118 }
2119
2120 if (strv_length(c->read_only_dirs) > 0) {
2121 fprintf(f, "%sReadOnlyDirs:", prefix);
2122 strv_fprintf(f, c->read_only_dirs);
2123 fputs("\n", f);
2124 }
94f04347 2125
15ae422b
LP
2126 if (strv_length(c->inaccessible_dirs) > 0) {
2127 fprintf(f, "%sInaccessibleDirs:", prefix);
2128 strv_fprintf(f, c->inaccessible_dirs);
94f04347
LP
2129 fputs("\n", f);
2130 }
2e22afe9 2131
169c1bda
LP
2132 if (c->utmp_id)
2133 fprintf(f,
2134 "%sUtmpIdentifier: %s\n",
2135 prefix, c->utmp_id);
7b52a628
MS
2136
2137 if (c->selinux_context)
2138 fprintf(f,
5f8640fb
LP
2139 "%sSELinuxContext: %s%s\n",
2140 prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context);
17df7223 2141
ac45f971
LP
2142 if (c->personality != 0xffffffffUL)
2143 fprintf(f,
2144 "%sPersonality: %s\n",
2145 prefix, strna(personality_to_string(c->personality)));
2146
17df7223 2147 if (c->syscall_filter) {
351a19b1 2148#ifdef HAVE_SECCOMP
17df7223
LP
2149 Iterator j;
2150 void *id;
2151 bool first = true;
351a19b1 2152#endif
17df7223
LP
2153
2154 fprintf(f,
57183d11 2155 "%sSystemCallFilter: ",
17df7223
LP
2156 prefix);
2157
2158 if (!c->syscall_whitelist)
2159 fputc('~', f);
2160
351a19b1 2161#ifdef HAVE_SECCOMP
17df7223
LP
2162 SET_FOREACH(id, c->syscall_filter, j) {
2163 _cleanup_free_ char *name = NULL;
2164
2165 if (first)
2166 first = false;
2167 else
2168 fputc(' ', f);
2169
57183d11 2170 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
17df7223
LP
2171 fputs(strna(name), f);
2172 }
351a19b1 2173#endif
17df7223
LP
2174
2175 fputc('\n', f);
2176 }
2177
57183d11
LP
2178 if (c->syscall_archs) {
2179#ifdef HAVE_SECCOMP
2180 Iterator j;
2181 void *id;
2182#endif
2183
2184 fprintf(f,
2185 "%sSystemCallArchitectures:",
2186 prefix);
2187
2188#ifdef HAVE_SECCOMP
2189 SET_FOREACH(id, c->syscall_archs, j)
2190 fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1)));
2191#endif
2192 fputc('\n', f);
2193 }
2194
17df7223
LP
2195 if (c->syscall_errno != 0)
2196 fprintf(f,
2197 "%sSystemCallErrorNumber: %s\n",
2198 prefix, strna(errno_to_name(c->syscall_errno)));
5cb5a6ff
LP
2199}
2200
b58b4116 2201void exec_status_start(ExecStatus *s, pid_t pid) {
034c6ed7 2202 assert(s);
5cb5a6ff 2203
b58b4116
LP
2204 zero(*s);
2205 s->pid = pid;
2206 dual_timestamp_get(&s->start_timestamp);
2207}
2208
6ea832a2 2209void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status) {
b58b4116
LP
2210 assert(s);
2211
0b1f4ae6 2212 if (s->pid && s->pid != pid)
b58b4116
LP
2213 zero(*s);
2214
034c6ed7 2215 s->pid = pid;
63983207 2216 dual_timestamp_get(&s->exit_timestamp);
9fb86720 2217
034c6ed7
LP
2218 s->code = code;
2219 s->status = status;
169c1bda 2220
6ea832a2
LP
2221 if (context) {
2222 if (context->utmp_id)
2223 utmp_put_dead_process(context->utmp_id, pid, code, status);
2224
2225 exec_context_tty_reset(context);
2226 }
9fb86720
LP
2227}
2228
2229void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
2230 char buf[FORMAT_TIMESTAMP_MAX];
2231
2232 assert(s);
2233 assert(f);
2234
2235 if (!prefix)
2236 prefix = "";
2237
2238 if (s->pid <= 0)
2239 return;
2240
2241 fprintf(f,
ccd06097
ZJS
2242 "%sPID: "PID_FMT"\n",
2243 prefix, s->pid);
9fb86720 2244
63983207 2245 if (s->start_timestamp.realtime > 0)
9fb86720
LP
2246 fprintf(f,
2247 "%sStart Timestamp: %s\n",
63983207 2248 prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
9fb86720 2249
63983207 2250 if (s->exit_timestamp.realtime > 0)
9fb86720
LP
2251 fprintf(f,
2252 "%sExit Timestamp: %s\n"
2253 "%sExit Code: %s\n"
2254 "%sExit Status: %i\n",
63983207 2255 prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
9fb86720
LP
2256 prefix, sigchld_code_to_string(s->code),
2257 prefix, s->status);
5cb5a6ff 2258}
44d8db9e 2259
9e2f7c11 2260char *exec_command_line(char **argv) {
44d8db9e
LP
2261 size_t k;
2262 char *n, *p, **a;
2263 bool first = true;
2264
9e2f7c11 2265 assert(argv);
44d8db9e 2266
9164977d 2267 k = 1;
9e2f7c11 2268 STRV_FOREACH(a, argv)
44d8db9e
LP
2269 k += strlen(*a)+3;
2270
2271 if (!(n = new(char, k)))
2272 return NULL;
2273
2274 p = n;
9e2f7c11 2275 STRV_FOREACH(a, argv) {
44d8db9e
LP
2276
2277 if (!first)
2278 *(p++) = ' ';
2279 else
2280 first = false;
2281
2282 if (strpbrk(*a, WHITESPACE)) {
2283 *(p++) = '\'';
2284 p = stpcpy(p, *a);
2285 *(p++) = '\'';
2286 } else
2287 p = stpcpy(p, *a);
2288
2289 }
2290
9164977d
LP
2291 *p = 0;
2292
44d8db9e
LP
2293 /* FIXME: this doesn't really handle arguments that have
2294 * spaces and ticks in them */
2295
2296 return n;
2297}
2298
2299void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
9fb86720
LP
2300 char *p2;
2301 const char *prefix2;
2302
44d8db9e
LP
2303 char *cmd;
2304
2305 assert(c);
2306 assert(f);
2307
2308 if (!prefix)
2309 prefix = "";
9fb86720
LP
2310 p2 = strappend(prefix, "\t");
2311 prefix2 = p2 ? p2 : prefix;
44d8db9e 2312
9e2f7c11 2313 cmd = exec_command_line(c->argv);
44d8db9e
LP
2314
2315 fprintf(f,
2316 "%sCommand Line: %s\n",
2317 prefix, cmd ? cmd : strerror(ENOMEM));
2318
2319 free(cmd);
9fb86720
LP
2320
2321 exec_status_dump(&c->exec_status, f, prefix2);
2322
2323 free(p2);
44d8db9e
LP
2324}
2325
2326void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
2327 assert(f);
2328
2329 if (!prefix)
2330 prefix = "";
2331
2332 LIST_FOREACH(command, c, c)
2333 exec_command_dump(c, f, prefix);
2334}
94f04347 2335
a6a80b4f
LP
2336void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
2337 ExecCommand *end;
2338
2339 assert(l);
2340 assert(e);
2341
2342 if (*l) {
35b8ca3a 2343 /* It's kind of important, that we keep the order here */
71fda00f
LP
2344 LIST_FIND_TAIL(command, *l, end);
2345 LIST_INSERT_AFTER(command, *l, end, e);
a6a80b4f
LP
2346 } else
2347 *l = e;
2348}
2349
26fd040d
LP
2350int exec_command_set(ExecCommand *c, const char *path, ...) {
2351 va_list ap;
2352 char **l, *p;
2353
2354 assert(c);
2355 assert(path);
2356
2357 va_start(ap, path);
2358 l = strv_new_ap(path, ap);
2359 va_end(ap);
2360
2361 if (!l)
2362 return -ENOMEM;
2363
250a918d
LP
2364 p = strdup(path);
2365 if (!p) {
26fd040d
LP
2366 strv_free(l);
2367 return -ENOMEM;
2368 }
2369
2370 free(c->path);
2371 c->path = p;
2372
2373 strv_free(c->argv);
2374 c->argv = l;
2375
2376 return 0;
2377}
2378
613b411c
LP
2379static int exec_runtime_allocate(ExecRuntime **rt) {
2380
2381 if (*rt)
2382 return 0;
2383
2384 *rt = new0(ExecRuntime, 1);
f146f5e1 2385 if (!*rt)
613b411c
LP
2386 return -ENOMEM;
2387
2388 (*rt)->n_ref = 1;
2389 (*rt)->netns_storage_socket[0] = (*rt)->netns_storage_socket[1] = -1;
2390
2391 return 0;
2392}
2393
2394int exec_runtime_make(ExecRuntime **rt, ExecContext *c, const char *id) {
2395 int r;
2396
2397 assert(rt);
2398 assert(c);
2399 assert(id);
2400
2401 if (*rt)
2402 return 1;
2403
2404 if (!c->private_network && !c->private_tmp)
2405 return 0;
2406
2407 r = exec_runtime_allocate(rt);
2408 if (r < 0)
2409 return r;
2410
2411 if (c->private_network && (*rt)->netns_storage_socket[0] < 0) {
2412 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, (*rt)->netns_storage_socket) < 0)
2413 return -errno;
2414 }
2415
2416 if (c->private_tmp && !(*rt)->tmp_dir) {
2417 r = setup_tmp_dirs(id, &(*rt)->tmp_dir, &(*rt)->var_tmp_dir);
2418 if (r < 0)
2419 return r;
2420 }
2421
2422 return 1;
2423}
2424
2425ExecRuntime *exec_runtime_ref(ExecRuntime *r) {
2426 assert(r);
2427 assert(r->n_ref > 0);
2428
2429 r->n_ref++;
2430 return r;
2431}
2432
2433ExecRuntime *exec_runtime_unref(ExecRuntime *r) {
2434
2435 if (!r)
2436 return NULL;
2437
2438 assert(r->n_ref > 0);
2439
2440 r->n_ref--;
2441 if (r->n_ref <= 0) {
2442 free(r->tmp_dir);
2443 free(r->var_tmp_dir);
2444 close_pipe(r->netns_storage_socket);
2445 free(r);
2446 }
2447
2448 return NULL;
2449}
2450
2451int exec_runtime_serialize(ExecRuntime *rt, Unit *u, FILE *f, FDSet *fds) {
2452 assert(u);
2453 assert(f);
2454 assert(fds);
2455
2456 if (!rt)
2457 return 0;
2458
2459 if (rt->tmp_dir)
2460 unit_serialize_item(u, f, "tmp-dir", rt->tmp_dir);
2461
2462 if (rt->var_tmp_dir)
2463 unit_serialize_item(u, f, "var-tmp-dir", rt->var_tmp_dir);
2464
2465 if (rt->netns_storage_socket[0] >= 0) {
2466 int copy;
2467
2468 copy = fdset_put_dup(fds, rt->netns_storage_socket[0]);
2469 if (copy < 0)
2470 return copy;
2471
2472 unit_serialize_item_format(u, f, "netns-socket-0", "%i", copy);
2473 }
2474
2475 if (rt->netns_storage_socket[1] >= 0) {
2476 int copy;
2477
2478 copy = fdset_put_dup(fds, rt->netns_storage_socket[1]);
2479 if (copy < 0)
2480 return copy;
2481
2482 unit_serialize_item_format(u, f, "netns-socket-1", "%i", copy);
2483 }
2484
2485 return 0;
2486}
2487
2488int exec_runtime_deserialize_item(ExecRuntime **rt, Unit *u, const char *key, const char *value, FDSet *fds) {
2489 int r;
2490
2491 assert(rt);
2492 assert(key);
2493 assert(value);
2494
2495 if (streq(key, "tmp-dir")) {
2496 char *copy;
2497
2498 r = exec_runtime_allocate(rt);
2499 if (r < 0)
2500 return r;
2501
2502 copy = strdup(value);
2503 if (!copy)
2504 return log_oom();
2505
2506 free((*rt)->tmp_dir);
2507 (*rt)->tmp_dir = copy;
2508
2509 } else if (streq(key, "var-tmp-dir")) {
2510 char *copy;
2511
2512 r = exec_runtime_allocate(rt);
2513 if (r < 0)
2514 return r;
2515
2516 copy = strdup(value);
2517 if (!copy)
2518 return log_oom();
2519
2520 free((*rt)->var_tmp_dir);
2521 (*rt)->var_tmp_dir = copy;
2522
2523 } else if (streq(key, "netns-socket-0")) {
2524 int fd;
2525
2526 r = exec_runtime_allocate(rt);
2527 if (r < 0)
2528 return r;
2529
2530 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
2531 log_debug_unit(u->id, "Failed to parse netns socket value %s", value);
2532 else {
2533 if ((*rt)->netns_storage_socket[0] >= 0)
2534 close_nointr_nofail((*rt)->netns_storage_socket[0]);
2535
2536 (*rt)->netns_storage_socket[0] = fdset_remove(fds, fd);
2537 }
2538 } else if (streq(key, "netns-socket-1")) {
2539 int fd;
2540
2541 r = exec_runtime_allocate(rt);
2542 if (r < 0)
2543 return r;
2544
2545 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
2546 log_debug_unit(u->id, "Failed to parse netns socket value %s", value);
2547 else {
2548 if ((*rt)->netns_storage_socket[1] >= 0)
2549 close_nointr_nofail((*rt)->netns_storage_socket[1]);
2550
2551 (*rt)->netns_storage_socket[1] = fdset_remove(fds, fd);
2552 }
2553 } else
2554 return 0;
2555
2556 return 1;
2557}
2558
2559static void *remove_tmpdir_thread(void *p) {
2560 _cleanup_free_ char *path = p;
2561
2562 rm_rf_dangerous(path, false, true, false);
2563 return NULL;
2564}
2565
2566void exec_runtime_destroy(ExecRuntime *rt) {
2567 if (!rt)
2568 return;
2569
2570 /* If there are multiple users of this, let's leave the stuff around */
2571 if (rt->n_ref > 1)
2572 return;
2573
2574 if (rt->tmp_dir) {
2575 log_debug("Spawning thread to nuke %s", rt->tmp_dir);
2576 asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
2577 rt->tmp_dir = NULL;
2578 }
2579
2580 if (rt->var_tmp_dir) {
2581 log_debug("Spawning thread to nuke %s", rt->var_tmp_dir);
2582 asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
2583 rt->var_tmp_dir = NULL;
2584 }
2585
2586 close_pipe(rt->netns_storage_socket);
2587}
2588
80876c20
LP
2589static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
2590 [EXEC_INPUT_NULL] = "null",
2591 [EXEC_INPUT_TTY] = "tty",
2592 [EXEC_INPUT_TTY_FORCE] = "tty-force",
4f2d528d
LP
2593 [EXEC_INPUT_TTY_FAIL] = "tty-fail",
2594 [EXEC_INPUT_SOCKET] = "socket"
80876c20
LP
2595};
2596
8a0867d6
LP
2597DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
2598
94f04347 2599static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
80876c20 2600 [EXEC_OUTPUT_INHERIT] = "inherit",
94f04347 2601 [EXEC_OUTPUT_NULL] = "null",
80876c20 2602 [EXEC_OUTPUT_TTY] = "tty",
94f04347 2603 [EXEC_OUTPUT_SYSLOG] = "syslog",
28dbc1e8 2604 [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
9a6bca7a 2605 [EXEC_OUTPUT_KMSG] = "kmsg",
28dbc1e8 2606 [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
706343f4
LP
2607 [EXEC_OUTPUT_JOURNAL] = "journal",
2608 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
4f2d528d 2609 [EXEC_OUTPUT_SOCKET] = "socket"
94f04347
LP
2610};
2611
2612DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);