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