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