]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/execute.c
tests: Add capability tests for ProtectKernelLogs
[thirdparty/systemd.git] / src / core / execute.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7334b09 2
034c6ed7
LP
3#include <errno.h>
4#include <fcntl.h>
8dd4c05b 5#include <poll.h>
d251207d 6#include <sys/eventfd.h>
f5947a5e 7#include <sys/ioctl.h>
f3e43635 8#include <sys/mman.h>
8dd4c05b 9#include <sys/personality.h>
94f04347 10#include <sys/prctl.h>
d2ffa389 11#include <sys/shm.h>
d2ffa389 12#include <sys/types.h>
8dd4c05b
LP
13#include <sys/un.h>
14#include <unistd.h>
023a4f67 15#include <utmpx.h>
5cb5a6ff 16
349cc4a5 17#if HAVE_PAM
5b6319dc
LP
18#include <security/pam_appl.h>
19#endif
20
349cc4a5 21#if HAVE_SELINUX
7b52a628
MS
22#include <selinux/selinux.h>
23#endif
24
349cc4a5 25#if HAVE_SECCOMP
17df7223
LP
26#include <seccomp.h>
27#endif
28
349cc4a5 29#if HAVE_APPARMOR
eef65bf3
MS
30#include <sys/apparmor.h>
31#endif
32
24882e06 33#include "sd-messages.h"
8dd4c05b
LP
34
35#include "af-list.h"
b5efdb8a 36#include "alloc-util.h"
349cc4a5 37#if HAVE_APPARMOR
3ffd4af2
LP
38#include "apparmor-util.h"
39#endif
8dd4c05b
LP
40#include "async.h"
41#include "barrier.h"
8dd4c05b 42#include "cap-list.h"
430f0182 43#include "capability-util.h"
a1164ae3 44#include "chown-recursive.h"
fdb3deca 45#include "cgroup-setup.h"
da681e1b 46#include "cpu-set-util.h"
f6a6225e 47#include "def.h"
686d13b9 48#include "env-file.h"
4d1a6904 49#include "env-util.h"
17df7223 50#include "errno-list.h"
3ffd4af2 51#include "execute.h"
8dd4c05b 52#include "exit-status.h"
3ffd4af2 53#include "fd-util.h"
f97b34a6 54#include "format-util.h"
f4f15635 55#include "fs-util.h"
7d50b32a 56#include "glob-util.h"
c004493c 57#include "io-util.h"
8dd4c05b 58#include "ioprio.h"
a1164ae3 59#include "label.h"
8dd4c05b
LP
60#include "log.h"
61#include "macro.h"
e8a565cb 62#include "manager.h"
0a970718 63#include "memory-util.h"
f5947a5e 64#include "missing_fs.h"
8dd4c05b
LP
65#include "mkdir.h"
66#include "namespace.h"
6bedfcbb 67#include "parse-util.h"
8dd4c05b 68#include "path-util.h"
0b452006 69#include "process-util.h"
78f22b97 70#include "rlimit-util.h"
8dd4c05b 71#include "rm-rf.h"
349cc4a5 72#if HAVE_SECCOMP
3ffd4af2
LP
73#include "seccomp-util.h"
74#endif
07d46372 75#include "securebits-util.h"
8dd4c05b 76#include "selinux-util.h"
24882e06 77#include "signal-util.h"
8dd4c05b 78#include "smack-util.h"
57b7a260 79#include "socket-util.h"
fd63e712 80#include "special.h"
949befd3 81#include "stat-util.h"
8b43440b 82#include "string-table.h"
07630cea 83#include "string-util.h"
8dd4c05b 84#include "strv.h"
7ccbd1ae 85#include "syslog-util.h"
8dd4c05b 86#include "terminal-util.h"
566b7d23 87#include "umask-util.h"
8dd4c05b 88#include "unit.h"
b1d4f8e1 89#include "user-util.h"
8dd4c05b 90#include "utmp-wtmp.h"
5cb5a6ff 91
e056b01d 92#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
31a7eb86 93#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
e6a26745 94
531dca78
LP
95#define SNDBUF_SIZE (8*1024*1024)
96
da6053d0 97static int shift_fds(int fds[], size_t n_fds) {
034c6ed7
LP
98 int start, restart_from;
99
100 if (n_fds <= 0)
101 return 0;
102
a0d40ac5
LP
103 /* Modifies the fds array! (sorts it) */
104
034c6ed7
LP
105 assert(fds);
106
107 start = 0;
108 for (;;) {
109 int i;
110
111 restart_from = -1;
112
113 for (i = start; i < (int) n_fds; i++) {
114 int nfd;
115
116 /* Already at right index? */
117 if (fds[i] == i+3)
118 continue;
119
3cc2aff1
LP
120 nfd = fcntl(fds[i], F_DUPFD, i + 3);
121 if (nfd < 0)
034c6ed7
LP
122 return -errno;
123
03e334a1 124 safe_close(fds[i]);
034c6ed7
LP
125 fds[i] = nfd;
126
127 /* Hmm, the fd we wanted isn't free? Then
ee33e53a 128 * let's remember that and try again from here */
034c6ed7
LP
129 if (nfd != i+3 && restart_from < 0)
130 restart_from = i;
131 }
132
133 if (restart_from < 0)
134 break;
135
136 start = restart_from;
137 }
138
139 return 0;
140}
141
25b583d7 142static int flags_fds(const int fds[], size_t n_socket_fds, size_t n_storage_fds, bool nonblock) {
da6053d0 143 size_t i, n_fds;
e2c76839 144 int r;
47a71eed 145
25b583d7 146 n_fds = n_socket_fds + n_storage_fds;
47a71eed
LP
147 if (n_fds <= 0)
148 return 0;
149
150 assert(fds);
151
9b141911
FB
152 /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags.
153 * O_NONBLOCK only applies to socket activation though. */
47a71eed
LP
154
155 for (i = 0; i < n_fds; i++) {
47a71eed 156
9b141911
FB
157 if (i < n_socket_fds) {
158 r = fd_nonblock(fds[i], nonblock);
159 if (r < 0)
160 return r;
161 }
47a71eed 162
451a074f
LP
163 /* We unconditionally drop FD_CLOEXEC from the fds,
164 * since after all we want to pass these fds to our
165 * children */
47a71eed 166
3cc2aff1
LP
167 r = fd_cloexec(fds[i], false);
168 if (r < 0)
e2c76839 169 return r;
47a71eed
LP
170 }
171
172 return 0;
173}
174
1e22b5cd 175static const char *exec_context_tty_path(const ExecContext *context) {
80876c20
LP
176 assert(context);
177
1e22b5cd
LP
178 if (context->stdio_as_fds)
179 return NULL;
180
80876c20
LP
181 if (context->tty_path)
182 return context->tty_path;
183
184 return "/dev/console";
185}
186
1e22b5cd
LP
187static void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) {
188 const char *path;
189
6ea832a2
LP
190 assert(context);
191
1e22b5cd 192 path = exec_context_tty_path(context);
6ea832a2 193
1e22b5cd
LP
194 if (context->tty_vhangup) {
195 if (p && p->stdin_fd >= 0)
196 (void) terminal_vhangup_fd(p->stdin_fd);
197 else if (path)
198 (void) terminal_vhangup(path);
199 }
6ea832a2 200
1e22b5cd
LP
201 if (context->tty_reset) {
202 if (p && p->stdin_fd >= 0)
203 (void) reset_terminal_fd(p->stdin_fd, true);
204 else if (path)
205 (void) reset_terminal(path);
206 }
207
208 if (context->tty_vt_disallocate && path)
209 (void) vt_disallocate(path);
6ea832a2
LP
210}
211
6af760f3
LP
212static bool is_terminal_input(ExecInput i) {
213 return IN_SET(i,
214 EXEC_INPUT_TTY,
215 EXEC_INPUT_TTY_FORCE,
216 EXEC_INPUT_TTY_FAIL);
217}
218
3a1286b6 219static bool is_terminal_output(ExecOutput o) {
6af760f3
LP
220 return IN_SET(o,
221 EXEC_OUTPUT_TTY,
222 EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
223 EXEC_OUTPUT_KMSG_AND_CONSOLE,
224 EXEC_OUTPUT_JOURNAL_AND_CONSOLE);
225}
226
aac8c0c3
LP
227static bool is_syslog_output(ExecOutput o) {
228 return IN_SET(o,
229 EXEC_OUTPUT_SYSLOG,
230 EXEC_OUTPUT_SYSLOG_AND_CONSOLE);
231}
232
233static bool is_kmsg_output(ExecOutput o) {
234 return IN_SET(o,
235 EXEC_OUTPUT_KMSG,
236 EXEC_OUTPUT_KMSG_AND_CONSOLE);
237}
238
6af760f3
LP
239static bool exec_context_needs_term(const ExecContext *c) {
240 assert(c);
241
242 /* Return true if the execution context suggests we should set $TERM to something useful. */
243
244 if (is_terminal_input(c->std_input))
245 return true;
246
247 if (is_terminal_output(c->std_output))
248 return true;
249
250 if (is_terminal_output(c->std_error))
251 return true;
252
253 return !!c->tty_path;
3a1286b6
MS
254}
255
80876c20 256static int open_null_as(int flags, int nfd) {
046a82c1 257 int fd;
071830ff 258
80876c20 259 assert(nfd >= 0);
071830ff 260
613b411c
LP
261 fd = open("/dev/null", flags|O_NOCTTY);
262 if (fd < 0)
071830ff
LP
263 return -errno;
264
046a82c1 265 return move_fd(fd, nfd, false);
071830ff
LP
266}
267
524daa8c 268static int connect_journal_socket(int fd, uid_t uid, gid_t gid) {
92a17af9 269 static const union sockaddr_union sa = {
b92bea5d
ZJS
270 .un.sun_family = AF_UNIX,
271 .un.sun_path = "/run/systemd/journal/stdout",
272 };
524daa8c
ZJS
273 uid_t olduid = UID_INVALID;
274 gid_t oldgid = GID_INVALID;
275 int r;
276
cad93f29 277 if (gid_is_valid(gid)) {
524daa8c
ZJS
278 oldgid = getgid();
279
92a17af9 280 if (setegid(gid) < 0)
524daa8c
ZJS
281 return -errno;
282 }
283
cad93f29 284 if (uid_is_valid(uid)) {
524daa8c
ZJS
285 olduid = getuid();
286
92a17af9 287 if (seteuid(uid) < 0) {
524daa8c
ZJS
288 r = -errno;
289 goto restore_gid;
290 }
291 }
292
92a17af9 293 r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0 ? -errno : 0;
524daa8c
ZJS
294
295 /* If we fail to restore the uid or gid, things will likely
296 fail later on. This should only happen if an LSM interferes. */
297
cad93f29 298 if (uid_is_valid(uid))
524daa8c
ZJS
299 (void) seteuid(olduid);
300
301 restore_gid:
cad93f29 302 if (gid_is_valid(gid))
524daa8c
ZJS
303 (void) setegid(oldgid);
304
305 return r;
306}
307
fd1f9c89 308static int connect_logger_as(
34cf6c43 309 const Unit *unit,
fd1f9c89 310 const ExecContext *context,
af635cf3 311 const ExecParameters *params,
fd1f9c89
LP
312 ExecOutput output,
313 const char *ident,
fd1f9c89
LP
314 int nfd,
315 uid_t uid,
316 gid_t gid) {
317
2ac1ff68
EV
318 _cleanup_close_ int fd = -1;
319 int r;
071830ff
LP
320
321 assert(context);
af635cf3 322 assert(params);
80876c20
LP
323 assert(output < _EXEC_OUTPUT_MAX);
324 assert(ident);
325 assert(nfd >= 0);
071830ff 326
54fe0cdb
LP
327 fd = socket(AF_UNIX, SOCK_STREAM, 0);
328 if (fd < 0)
80876c20 329 return -errno;
071830ff 330
524daa8c
ZJS
331 r = connect_journal_socket(fd, uid, gid);
332 if (r < 0)
333 return r;
071830ff 334
2ac1ff68 335 if (shutdown(fd, SHUT_RD) < 0)
80876c20 336 return -errno;
071830ff 337
fd1f9c89 338 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
531dca78 339
2ac1ff68 340 if (dprintf(fd,
62bca2c6 341 "%s\n"
80876c20
LP
342 "%s\n"
343 "%i\n"
54fe0cdb
LP
344 "%i\n"
345 "%i\n"
346 "%i\n"
4f4a1dbf 347 "%i\n",
c867611e 348 context->syslog_identifier ?: ident,
af635cf3 349 params->flags & EXEC_PASS_LOG_UNIT ? unit->id : "",
54fe0cdb
LP
350 context->syslog_priority,
351 !!context->syslog_level_prefix,
aac8c0c3
LP
352 is_syslog_output(output),
353 is_kmsg_output(output),
2ac1ff68
EV
354 is_terminal_output(output)) < 0)
355 return -errno;
80876c20 356
2ac1ff68 357 return move_fd(TAKE_FD(fd), nfd, false);
80876c20 358}
2ac1ff68 359
3a274a21 360static int open_terminal_as(const char *path, int flags, int nfd) {
046a82c1 361 int fd;
071830ff 362
80876c20
LP
363 assert(path);
364 assert(nfd >= 0);
fd1f9c89 365
3a274a21 366 fd = open_terminal(path, flags | O_NOCTTY);
3cc2aff1 367 if (fd < 0)
80876c20 368 return fd;
071830ff 369
046a82c1 370 return move_fd(fd, nfd, false);
80876c20 371}
071830ff 372
2038c3f5 373static int acquire_path(const char *path, int flags, mode_t mode) {
15a3e96f
LP
374 union sockaddr_union sa = {};
375 _cleanup_close_ int fd = -1;
376 int r, salen;
071830ff 377
80876c20 378 assert(path);
071830ff 379
2038c3f5
LP
380 if (IN_SET(flags & O_ACCMODE, O_WRONLY, O_RDWR))
381 flags |= O_CREAT;
382
383 fd = open(path, flags|O_NOCTTY, mode);
384 if (fd >= 0)
15a3e96f 385 return TAKE_FD(fd);
071830ff 386
2038c3f5
LP
387 if (errno != ENXIO) /* ENXIO is returned when we try to open() an AF_UNIX file system socket on Linux */
388 return -errno;
15a3e96f 389 if (strlen(path) >= sizeof(sa.un.sun_path)) /* Too long, can't be a UNIX socket */
2038c3f5
LP
390 return -ENXIO;
391
392 /* So, it appears the specified path could be an AF_UNIX socket. Let's see if we can connect to it. */
393
394 fd = socket(AF_UNIX, SOCK_STREAM, 0);
395 if (fd < 0)
396 return -errno;
397
15a3e96f
LP
398 salen = sockaddr_un_set_path(&sa.un, path);
399 if (salen < 0)
400 return salen;
401
402 if (connect(fd, &sa.sa, salen) < 0)
2038c3f5
LP
403 return errno == EINVAL ? -ENXIO : -errno; /* Propagate initial error if we get EINVAL, i.e. we have
404 * indication that his wasn't an AF_UNIX socket after all */
071830ff 405
2038c3f5
LP
406 if ((flags & O_ACCMODE) == O_RDONLY)
407 r = shutdown(fd, SHUT_WR);
408 else if ((flags & O_ACCMODE) == O_WRONLY)
409 r = shutdown(fd, SHUT_RD);
410 else
15a3e96f
LP
411 return TAKE_FD(fd);
412 if (r < 0)
2038c3f5 413 return -errno;
2038c3f5 414
15a3e96f 415 return TAKE_FD(fd);
80876c20 416}
071830ff 417
08f3be7a
LP
418static int fixup_input(
419 const ExecContext *context,
420 int socket_fd,
421 bool apply_tty_stdin) {
422
423 ExecInput std_input;
424
425 assert(context);
426
427 std_input = context->std_input;
1e3ad081
LP
428
429 if (is_terminal_input(std_input) && !apply_tty_stdin)
430 return EXEC_INPUT_NULL;
071830ff 431
03fd9c49 432 if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
4f2d528d
LP
433 return EXEC_INPUT_NULL;
434
08f3be7a
LP
435 if (std_input == EXEC_INPUT_DATA && context->stdin_data_size == 0)
436 return EXEC_INPUT_NULL;
437
03fd9c49 438 return std_input;
4f2d528d
LP
439}
440
03fd9c49 441static int fixup_output(ExecOutput std_output, int socket_fd) {
4f2d528d 442
03fd9c49 443 if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
4f2d528d
LP
444 return EXEC_OUTPUT_INHERIT;
445
03fd9c49 446 return std_output;
4f2d528d
LP
447}
448
a34ceba6
LP
449static int setup_input(
450 const ExecContext *context,
451 const ExecParameters *params,
52c239d7 452 int socket_fd,
2caa38e9 453 const int named_iofds[static 3]) {
a34ceba6 454
4f2d528d
LP
455 ExecInput i;
456
457 assert(context);
a34ceba6 458 assert(params);
2caa38e9 459 assert(named_iofds);
a34ceba6
LP
460
461 if (params->stdin_fd >= 0) {
462 if (dup2(params->stdin_fd, STDIN_FILENO) < 0)
463 return -errno;
464
465 /* Try to make this the controlling tty, if it is a tty, and reset it */
1fb0682e
LP
466 if (isatty(STDIN_FILENO)) {
467 (void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE);
468 (void) reset_terminal_fd(STDIN_FILENO, true);
469 }
a34ceba6
LP
470
471 return STDIN_FILENO;
472 }
4f2d528d 473
08f3be7a 474 i = fixup_input(context, socket_fd, params->flags & EXEC_APPLY_TTY_STDIN);
4f2d528d
LP
475
476 switch (i) {
071830ff 477
80876c20
LP
478 case EXEC_INPUT_NULL:
479 return open_null_as(O_RDONLY, STDIN_FILENO);
480
481 case EXEC_INPUT_TTY:
482 case EXEC_INPUT_TTY_FORCE:
483 case EXEC_INPUT_TTY_FAIL: {
046a82c1 484 int fd;
071830ff 485
1e22b5cd 486 fd = acquire_terminal(exec_context_tty_path(context),
8854d795
LP
487 i == EXEC_INPUT_TTY_FAIL ? ACQUIRE_TERMINAL_TRY :
488 i == EXEC_INPUT_TTY_FORCE ? ACQUIRE_TERMINAL_FORCE :
489 ACQUIRE_TERMINAL_WAIT,
3a43da28 490 USEC_INFINITY);
970edce6 491 if (fd < 0)
80876c20
LP
492 return fd;
493
046a82c1 494 return move_fd(fd, STDIN_FILENO, false);
80876c20
LP
495 }
496
4f2d528d 497 case EXEC_INPUT_SOCKET:
e75a9ed1
LP
498 assert(socket_fd >= 0);
499
4f2d528d
LP
500 return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
501
52c239d7 502 case EXEC_INPUT_NAMED_FD:
e75a9ed1
LP
503 assert(named_iofds[STDIN_FILENO] >= 0);
504
52c239d7
LB
505 (void) fd_nonblock(named_iofds[STDIN_FILENO], false);
506 return dup2(named_iofds[STDIN_FILENO], STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
507
08f3be7a
LP
508 case EXEC_INPUT_DATA: {
509 int fd;
510
511 fd = acquire_data_fd(context->stdin_data, context->stdin_data_size, 0);
512 if (fd < 0)
513 return fd;
514
515 return move_fd(fd, STDIN_FILENO, false);
516 }
517
2038c3f5
LP
518 case EXEC_INPUT_FILE: {
519 bool rw;
520 int fd;
521
522 assert(context->stdio_file[STDIN_FILENO]);
523
524 rw = (context->std_output == EXEC_OUTPUT_FILE && streq_ptr(context->stdio_file[STDIN_FILENO], context->stdio_file[STDOUT_FILENO])) ||
525 (context->std_error == EXEC_OUTPUT_FILE && streq_ptr(context->stdio_file[STDIN_FILENO], context->stdio_file[STDERR_FILENO]));
526
527 fd = acquire_path(context->stdio_file[STDIN_FILENO], rw ? O_RDWR : O_RDONLY, 0666 & ~context->umask);
528 if (fd < 0)
529 return fd;
530
531 return move_fd(fd, STDIN_FILENO, false);
532 }
533
80876c20
LP
534 default:
535 assert_not_reached("Unknown input type");
536 }
537}
538
41fc585a
LP
539static bool can_inherit_stderr_from_stdout(
540 const ExecContext *context,
541 ExecOutput o,
542 ExecOutput e) {
543
544 assert(context);
545
546 /* Returns true, if given the specified STDERR and STDOUT output we can directly dup() the stdout fd to the
547 * stderr fd */
548
549 if (e == EXEC_OUTPUT_INHERIT)
550 return true;
551 if (e != o)
552 return false;
553
554 if (e == EXEC_OUTPUT_NAMED_FD)
555 return streq_ptr(context->stdio_fdname[STDOUT_FILENO], context->stdio_fdname[STDERR_FILENO]);
556
557 if (IN_SET(e, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND))
558 return streq_ptr(context->stdio_file[STDOUT_FILENO], context->stdio_file[STDERR_FILENO]);
559
560 return true;
561}
562
a34ceba6 563static int setup_output(
34cf6c43 564 const Unit *unit,
a34ceba6
LP
565 const ExecContext *context,
566 const ExecParameters *params,
567 int fileno,
568 int socket_fd,
2caa38e9 569 const int named_iofds[static 3],
a34ceba6 570 const char *ident,
7bce046b
LP
571 uid_t uid,
572 gid_t gid,
573 dev_t *journal_stream_dev,
574 ino_t *journal_stream_ino) {
a34ceba6 575
4f2d528d
LP
576 ExecOutput o;
577 ExecInput i;
47c1d80d 578 int r;
4f2d528d 579
f2341e0a 580 assert(unit);
80876c20 581 assert(context);
a34ceba6 582 assert(params);
80876c20 583 assert(ident);
7bce046b
LP
584 assert(journal_stream_dev);
585 assert(journal_stream_ino);
80876c20 586
a34ceba6
LP
587 if (fileno == STDOUT_FILENO && params->stdout_fd >= 0) {
588
589 if (dup2(params->stdout_fd, STDOUT_FILENO) < 0)
590 return -errno;
591
592 return STDOUT_FILENO;
593 }
594
595 if (fileno == STDERR_FILENO && params->stderr_fd >= 0) {
596 if (dup2(params->stderr_fd, STDERR_FILENO) < 0)
597 return -errno;
598
599 return STDERR_FILENO;
600 }
601
08f3be7a 602 i = fixup_input(context, socket_fd, params->flags & EXEC_APPLY_TTY_STDIN);
03fd9c49 603 o = fixup_output(context->std_output, socket_fd);
4f2d528d 604
eb17e935
MS
605 if (fileno == STDERR_FILENO) {
606 ExecOutput e;
607 e = fixup_output(context->std_error, socket_fd);
80876c20 608
eb17e935
MS
609 /* This expects the input and output are already set up */
610
611 /* Don't change the stderr file descriptor if we inherit all
612 * the way and are not on a tty */
613 if (e == EXEC_OUTPUT_INHERIT &&
614 o == EXEC_OUTPUT_INHERIT &&
615 i == EXEC_INPUT_NULL &&
616 !is_terminal_input(context->std_input) &&
617 getppid () != 1)
618 return fileno;
619
620 /* Duplicate from stdout if possible */
41fc585a 621 if (can_inherit_stderr_from_stdout(context, o, e))
eb17e935 622 return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
071830ff 623
eb17e935 624 o = e;
80876c20 625
eb17e935 626 } else if (o == EXEC_OUTPUT_INHERIT) {
21d21ea4
LP
627 /* If input got downgraded, inherit the original value */
628 if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
1e22b5cd 629 return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno);
21d21ea4 630
08f3be7a
LP
631 /* If the input is connected to anything that's not a /dev/null or a data fd, inherit that... */
632 if (!IN_SET(i, EXEC_INPUT_NULL, EXEC_INPUT_DATA))
eb17e935 633 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
071830ff 634
acb591e4
LP
635 /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
636 if (getppid() != 1)
eb17e935 637 return fileno;
94f04347 638
eb17e935
MS
639 /* We need to open /dev/null here anew, to get the right access mode. */
640 return open_null_as(O_WRONLY, fileno);
071830ff 641 }
94f04347 642
eb17e935 643 switch (o) {
80876c20
LP
644
645 case EXEC_OUTPUT_NULL:
eb17e935 646 return open_null_as(O_WRONLY, fileno);
80876c20
LP
647
648 case EXEC_OUTPUT_TTY:
4f2d528d 649 if (is_terminal_input(i))
eb17e935 650 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
80876c20
LP
651
652 /* We don't reset the terminal if this is just about output */
1e22b5cd 653 return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno);
80876c20
LP
654
655 case EXEC_OUTPUT_SYSLOG:
28dbc1e8 656 case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
9a6bca7a 657 case EXEC_OUTPUT_KMSG:
28dbc1e8 658 case EXEC_OUTPUT_KMSG_AND_CONSOLE:
706343f4
LP
659 case EXEC_OUTPUT_JOURNAL:
660 case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
af635cf3 661 r = connect_logger_as(unit, context, params, o, ident, fileno, uid, gid);
47c1d80d 662 if (r < 0) {
82677ae4 663 log_unit_warning_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr");
eb17e935 664 r = open_null_as(O_WRONLY, fileno);
7bce046b
LP
665 } else {
666 struct stat st;
667
668 /* If we connected this fd to the journal via a stream, patch the device/inode into the passed
669 * parameters, but only then. This is useful so that we can set $JOURNAL_STREAM that permits
ab2116b1
LP
670 * services to detect whether they are connected to the journal or not.
671 *
672 * If both stdout and stderr are connected to a stream then let's make sure to store the data
673 * about STDERR as that's usually the best way to do logging. */
7bce046b 674
ab2116b1
LP
675 if (fstat(fileno, &st) >= 0 &&
676 (*journal_stream_ino == 0 || fileno == STDERR_FILENO)) {
7bce046b
LP
677 *journal_stream_dev = st.st_dev;
678 *journal_stream_ino = st.st_ino;
679 }
47c1d80d
MS
680 }
681 return r;
4f2d528d
LP
682
683 case EXEC_OUTPUT_SOCKET:
684 assert(socket_fd >= 0);
e75a9ed1 685
eb17e935 686 return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
94f04347 687
52c239d7 688 case EXEC_OUTPUT_NAMED_FD:
e75a9ed1
LP
689 assert(named_iofds[fileno] >= 0);
690
52c239d7
LB
691 (void) fd_nonblock(named_iofds[fileno], false);
692 return dup2(named_iofds[fileno], fileno) < 0 ? -errno : fileno;
693
566b7d23
ZD
694 case EXEC_OUTPUT_FILE:
695 case EXEC_OUTPUT_FILE_APPEND: {
2038c3f5 696 bool rw;
566b7d23 697 int fd, flags;
2038c3f5
LP
698
699 assert(context->stdio_file[fileno]);
700
701 rw = context->std_input == EXEC_INPUT_FILE &&
702 streq_ptr(context->stdio_file[fileno], context->stdio_file[STDIN_FILENO]);
703
704 if (rw)
705 return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
706
566b7d23
ZD
707 flags = O_WRONLY;
708 if (o == EXEC_OUTPUT_FILE_APPEND)
709 flags |= O_APPEND;
710
711 fd = acquire_path(context->stdio_file[fileno], flags, 0666 & ~context->umask);
2038c3f5
LP
712 if (fd < 0)
713 return fd;
714
566b7d23 715 return move_fd(fd, fileno, 0);
2038c3f5
LP
716 }
717
94f04347 718 default:
80876c20 719 assert_not_reached("Unknown error type");
94f04347 720 }
071830ff
LP
721}
722
02a51aba 723static int chown_terminal(int fd, uid_t uid) {
4b3b5bc7 724 int r;
02a51aba
LP
725
726 assert(fd >= 0);
02a51aba 727
1ff74fb6 728 /* Before we chown/chmod the TTY, let's ensure this is actually a tty */
4b3b5bc7
LP
729 if (isatty(fd) < 1) {
730 if (IN_SET(errno, EINVAL, ENOTTY))
731 return 0; /* not a tty */
1ff74fb6 732
02a51aba 733 return -errno;
4b3b5bc7 734 }
02a51aba 735
4b3b5bc7
LP
736 /* This might fail. What matters are the results. */
737 r = fchmod_and_chown(fd, TTY_MODE, uid, -1);
738 if (r < 0)
739 return r;
02a51aba 740
4b3b5bc7 741 return 1;
02a51aba
LP
742}
743
7d5ceb64 744static int setup_confirm_stdio(const char *vc, int *_saved_stdin, int *_saved_stdout) {
3d18b167
LP
745 _cleanup_close_ int fd = -1, saved_stdin = -1, saved_stdout = -1;
746 int r;
80876c20 747
80876c20
LP
748 assert(_saved_stdin);
749 assert(_saved_stdout);
750
af6da548
LP
751 saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
752 if (saved_stdin < 0)
753 return -errno;
80876c20 754
af6da548 755 saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
3d18b167
LP
756 if (saved_stdout < 0)
757 return -errno;
80876c20 758
8854d795 759 fd = acquire_terminal(vc, ACQUIRE_TERMINAL_WAIT, DEFAULT_CONFIRM_USEC);
3d18b167
LP
760 if (fd < 0)
761 return fd;
80876c20 762
af6da548
LP
763 r = chown_terminal(fd, getuid());
764 if (r < 0)
3d18b167 765 return r;
02a51aba 766
3d18b167
LP
767 r = reset_terminal_fd(fd, true);
768 if (r < 0)
769 return r;
80876c20 770
2b33ab09 771 r = rearrange_stdio(fd, fd, STDERR_FILENO);
3d18b167 772 fd = -1;
2b33ab09
LP
773 if (r < 0)
774 return r;
80876c20
LP
775
776 *_saved_stdin = saved_stdin;
777 *_saved_stdout = saved_stdout;
778
3d18b167 779 saved_stdin = saved_stdout = -1;
80876c20 780
3d18b167 781 return 0;
80876c20
LP
782}
783
63d77c92 784static void write_confirm_error_fd(int err, int fd, const Unit *u) {
3b20f877
FB
785 assert(err < 0);
786
787 if (err == -ETIMEDOUT)
63d77c92 788 dprintf(fd, "Confirmation question timed out for %s, assuming positive response.\n", u->id);
3b20f877
FB
789 else {
790 errno = -err;
63d77c92 791 dprintf(fd, "Couldn't ask confirmation for %s: %m, assuming positive response.\n", u->id);
3b20f877
FB
792 }
793}
794
63d77c92 795static void write_confirm_error(int err, const char *vc, const Unit *u) {
03e334a1 796 _cleanup_close_ int fd = -1;
80876c20 797
3b20f877 798 assert(vc);
80876c20 799
7d5ceb64 800 fd = open_terminal(vc, O_WRONLY|O_NOCTTY|O_CLOEXEC);
af6da548 801 if (fd < 0)
3b20f877 802 return;
80876c20 803
63d77c92 804 write_confirm_error_fd(err, fd, u);
af6da548 805}
80876c20 806
3d18b167 807static int restore_confirm_stdio(int *saved_stdin, int *saved_stdout) {
af6da548 808 int r = 0;
80876c20 809
af6da548
LP
810 assert(saved_stdin);
811 assert(saved_stdout);
812
813 release_terminal();
814
815 if (*saved_stdin >= 0)
80876c20 816 if (dup2(*saved_stdin, STDIN_FILENO) < 0)
af6da548 817 r = -errno;
80876c20 818
af6da548 819 if (*saved_stdout >= 0)
80876c20 820 if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
af6da548 821 r = -errno;
80876c20 822
3d18b167
LP
823 *saved_stdin = safe_close(*saved_stdin);
824 *saved_stdout = safe_close(*saved_stdout);
af6da548
LP
825
826 return r;
827}
828
3b20f877
FB
829enum {
830 CONFIRM_PRETEND_FAILURE = -1,
831 CONFIRM_PRETEND_SUCCESS = 0,
832 CONFIRM_EXECUTE = 1,
833};
834
eedf223a 835static int ask_for_confirmation(const char *vc, Unit *u, const char *cmdline) {
af6da548 836 int saved_stdout = -1, saved_stdin = -1, r;
2bcd3c26 837 _cleanup_free_ char *e = NULL;
3b20f877 838 char c;
af6da548 839
3b20f877 840 /* For any internal errors, assume a positive response. */
7d5ceb64 841 r = setup_confirm_stdio(vc, &saved_stdin, &saved_stdout);
3b20f877 842 if (r < 0) {
63d77c92 843 write_confirm_error(r, vc, u);
3b20f877
FB
844 return CONFIRM_EXECUTE;
845 }
af6da548 846
b0eb2944
FB
847 /* confirm_spawn might have been disabled while we were sleeping. */
848 if (manager_is_confirm_spawn_disabled(u->manager)) {
849 r = 1;
850 goto restore_stdio;
851 }
af6da548 852
2bcd3c26
FB
853 e = ellipsize(cmdline, 60, 100);
854 if (!e) {
855 log_oom();
856 r = CONFIRM_EXECUTE;
857 goto restore_stdio;
858 }
af6da548 859
d172b175 860 for (;;) {
539622bd 861 r = ask_char(&c, "yfshiDjcn", "Execute %s? [y, f, s – h for help] ", e);
d172b175 862 if (r < 0) {
63d77c92 863 write_confirm_error_fd(r, STDOUT_FILENO, u);
d172b175
FB
864 r = CONFIRM_EXECUTE;
865 goto restore_stdio;
866 }
af6da548 867
d172b175 868 switch (c) {
b0eb2944
FB
869 case 'c':
870 printf("Resuming normal execution.\n");
871 manager_disable_confirm_spawn();
872 r = 1;
873 break;
dd6f9ac0
FB
874 case 'D':
875 unit_dump(u, stdout, " ");
876 continue; /* ask again */
d172b175
FB
877 case 'f':
878 printf("Failing execution.\n");
879 r = CONFIRM_PRETEND_FAILURE;
880 break;
881 case 'h':
b0eb2944
FB
882 printf(" c - continue, proceed without asking anymore\n"
883 " D - dump, show the state of the unit\n"
dd6f9ac0 884 " f - fail, don't execute the command and pretend it failed\n"
d172b175 885 " h - help\n"
eedf223a 886 " i - info, show a short summary of the unit\n"
56fde33a 887 " j - jobs, show jobs that are in progress\n"
d172b175
FB
888 " s - skip, don't execute the command and pretend it succeeded\n"
889 " y - yes, execute the command\n");
dd6f9ac0 890 continue; /* ask again */
eedf223a
FB
891 case 'i':
892 printf(" Description: %s\n"
893 " Unit: %s\n"
894 " Command: %s\n",
895 u->id, u->description, cmdline);
896 continue; /* ask again */
56fde33a
FB
897 case 'j':
898 manager_dump_jobs(u->manager, stdout, " ");
899 continue; /* ask again */
539622bd
FB
900 case 'n':
901 /* 'n' was removed in favor of 'f'. */
902 printf("Didn't understand 'n', did you mean 'f'?\n");
903 continue; /* ask again */
d172b175
FB
904 case 's':
905 printf("Skipping execution.\n");
906 r = CONFIRM_PRETEND_SUCCESS;
907 break;
908 case 'y':
909 r = CONFIRM_EXECUTE;
910 break;
911 default:
912 assert_not_reached("Unhandled choice");
913 }
3b20f877 914 break;
3b20f877 915 }
af6da548 916
3b20f877 917restore_stdio:
af6da548 918 restore_confirm_stdio(&saved_stdin, &saved_stdout);
af6da548 919 return r;
80876c20
LP
920}
921
4d885bd3
DH
922static int get_fixed_user(const ExecContext *c, const char **user,
923 uid_t *uid, gid_t *gid,
924 const char **home, const char **shell) {
81a2b7ce 925 int r;
4d885bd3 926 const char *name;
81a2b7ce 927
4d885bd3 928 assert(c);
81a2b7ce 929
23deef88
LP
930 if (!c->user)
931 return 0;
932
4d885bd3
DH
933 /* Note that we don't set $HOME or $SHELL if they are not particularly enlightening anyway
934 * (i.e. are "/" or "/bin/nologin"). */
81a2b7ce 935
23deef88 936 name = c->user;
fafff8f1 937 r = get_user_creds(&name, uid, gid, home, shell, USER_CREDS_CLEAN);
4d885bd3
DH
938 if (r < 0)
939 return r;
81a2b7ce 940
4d885bd3
DH
941 *user = name;
942 return 0;
943}
944
945static int get_fixed_group(const ExecContext *c, const char **group, gid_t *gid) {
946 int r;
947 const char *name;
948
949 assert(c);
950
951 if (!c->group)
952 return 0;
953
954 name = c->group;
fafff8f1 955 r = get_group_creds(&name, gid, 0);
4d885bd3
DH
956 if (r < 0)
957 return r;
958
959 *group = name;
960 return 0;
961}
962
cdc5d5c5
DH
963static int get_supplementary_groups(const ExecContext *c, const char *user,
964 const char *group, gid_t gid,
965 gid_t **supplementary_gids, int *ngids) {
4d885bd3
DH
966 char **i;
967 int r, k = 0;
968 int ngroups_max;
969 bool keep_groups = false;
970 gid_t *groups = NULL;
971 _cleanup_free_ gid_t *l_gids = NULL;
972
973 assert(c);
974
bbeea271
DH
975 /*
976 * If user is given, then lookup GID and supplementary groups list.
977 * We avoid NSS lookups for gid=0. Also we have to initialize groups
cdc5d5c5
DH
978 * here and as early as possible so we keep the list of supplementary
979 * groups of the caller.
bbeea271
DH
980 */
981 if (user && gid_is_valid(gid) && gid != 0) {
982 /* First step, initialize groups from /etc/groups */
983 if (initgroups(user, gid) < 0)
984 return -errno;
985
986 keep_groups = true;
987 }
988
ac6e8be6 989 if (strv_isempty(c->supplementary_groups))
4d885bd3
DH
990 return 0;
991
366ddd25
DH
992 /*
993 * If SupplementaryGroups= was passed then NGROUPS_MAX has to
994 * be positive, otherwise fail.
995 */
996 errno = 0;
997 ngroups_max = (int) sysconf(_SC_NGROUPS_MAX);
66855de7
LP
998 if (ngroups_max <= 0)
999 return errno_or_else(EOPNOTSUPP);
366ddd25 1000
4d885bd3
DH
1001 l_gids = new(gid_t, ngroups_max);
1002 if (!l_gids)
1003 return -ENOMEM;
81a2b7ce 1004
4d885bd3
DH
1005 if (keep_groups) {
1006 /*
1007 * Lookup the list of groups that the user belongs to, we
1008 * avoid NSS lookups here too for gid=0.
1009 */
1010 k = ngroups_max;
1011 if (getgrouplist(user, gid, l_gids, &k) < 0)
1012 return -EINVAL;
1013 } else
1014 k = 0;
81a2b7ce 1015
4d885bd3
DH
1016 STRV_FOREACH(i, c->supplementary_groups) {
1017 const char *g;
81a2b7ce 1018
4d885bd3
DH
1019 if (k >= ngroups_max)
1020 return -E2BIG;
81a2b7ce 1021
4d885bd3 1022 g = *i;
fafff8f1 1023 r = get_group_creds(&g, l_gids+k, 0);
4d885bd3
DH
1024 if (r < 0)
1025 return r;
81a2b7ce 1026
4d885bd3
DH
1027 k++;
1028 }
81a2b7ce 1029
4d885bd3
DH
1030 /*
1031 * Sets ngids to zero to drop all supplementary groups, happens
1032 * when we are under root and SupplementaryGroups= is empty.
1033 */
1034 if (k == 0) {
1035 *ngids = 0;
1036 return 0;
1037 }
81a2b7ce 1038
4d885bd3
DH
1039 /* Otherwise get the final list of supplementary groups */
1040 groups = memdup(l_gids, sizeof(gid_t) * k);
1041 if (!groups)
1042 return -ENOMEM;
1043
1044 *supplementary_gids = groups;
1045 *ngids = k;
1046
1047 groups = NULL;
1048
1049 return 0;
1050}
1051
34cf6c43 1052static int enforce_groups(gid_t gid, const gid_t *supplementary_gids, int ngids) {
4d885bd3
DH
1053 int r;
1054
709dbeac
YW
1055 /* Handle SupplementaryGroups= if it is not empty */
1056 if (ngids > 0) {
4d885bd3
DH
1057 r = maybe_setgroups(ngids, supplementary_gids);
1058 if (r < 0)
97f0e76f 1059 return r;
4d885bd3 1060 }
81a2b7ce 1061
4d885bd3
DH
1062 if (gid_is_valid(gid)) {
1063 /* Then set our gids */
1064 if (setresgid(gid, gid, gid) < 0)
1065 return -errno;
81a2b7ce
LP
1066 }
1067
1068 return 0;
1069}
1070
1071static int enforce_user(const ExecContext *context, uid_t uid) {
81a2b7ce
LP
1072 assert(context);
1073
4d885bd3
DH
1074 if (!uid_is_valid(uid))
1075 return 0;
1076
479050b3 1077 /* Sets (but doesn't look up) the uid and make sure we keep the
81a2b7ce
LP
1078 * capabilities while doing so. */
1079
479050b3 1080 if (context->capability_ambient_set != 0) {
81a2b7ce
LP
1081
1082 /* First step: If we need to keep capabilities but
1083 * drop privileges we need to make sure we keep our
cbb21cca 1084 * caps, while we drop privileges. */
693ced48 1085 if (uid != 0) {
cbb21cca 1086 int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
693ced48
LP
1087
1088 if (prctl(PR_GET_SECUREBITS) != sb)
1089 if (prctl(PR_SET_SECUREBITS, sb) < 0)
1090 return -errno;
1091 }
81a2b7ce
LP
1092 }
1093
479050b3 1094 /* Second step: actually set the uids */
81a2b7ce
LP
1095 if (setresuid(uid, uid, uid) < 0)
1096 return -errno;
1097
1098 /* At this point we should have all necessary capabilities but
1099 are otherwise a normal user. However, the caps might got
1100 corrupted due to the setresuid() so we need clean them up
1101 later. This is done outside of this call. */
1102
1103 return 0;
1104}
1105
349cc4a5 1106#if HAVE_PAM
5b6319dc
LP
1107
1108static int null_conv(
1109 int num_msg,
1110 const struct pam_message **msg,
1111 struct pam_response **resp,
1112 void *appdata_ptr) {
1113
1114 /* We don't support conversations */
1115
1116 return PAM_CONV_ERR;
1117}
1118
cefc33ae
LP
1119#endif
1120
5b6319dc
LP
1121static int setup_pam(
1122 const char *name,
1123 const char *user,
940c5210 1124 uid_t uid,
2d6fce8d 1125 gid_t gid,
5b6319dc 1126 const char *tty,
2065ca69 1127 char ***env,
da6053d0 1128 int fds[], size_t n_fds) {
5b6319dc 1129
349cc4a5 1130#if HAVE_PAM
cefc33ae 1131
5b6319dc
LP
1132 static const struct pam_conv conv = {
1133 .conv = null_conv,
1134 .appdata_ptr = NULL
1135 };
1136
2d7c6aa2 1137 _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
5b6319dc 1138 pam_handle_t *handle = NULL;
d6e5f3ad 1139 sigset_t old_ss;
7bb70b6e 1140 int pam_code = PAM_SUCCESS, r;
84eada2f 1141 char **nv, **e = NULL;
5b6319dc
LP
1142 bool close_session = false;
1143 pid_t pam_pid = 0, parent_pid;
970edce6 1144 int flags = 0;
5b6319dc
LP
1145
1146 assert(name);
1147 assert(user);
2065ca69 1148 assert(env);
5b6319dc
LP
1149
1150 /* We set up PAM in the parent process, then fork. The child
35b8ca3a 1151 * will then stay around until killed via PR_GET_PDEATHSIG or
5b6319dc
LP
1152 * systemd via the cgroup logic. It will then remove the PAM
1153 * session again. The parent process will exec() the actual
1154 * daemon. We do things this way to ensure that the main PID
1155 * of the daemon is the one we initially fork()ed. */
1156
7bb70b6e
LP
1157 r = barrier_create(&barrier);
1158 if (r < 0)
2d7c6aa2
DH
1159 goto fail;
1160
553d2243 1161 if (log_get_max_level() < LOG_DEBUG)
970edce6
ZJS
1162 flags |= PAM_SILENT;
1163
f546241b
ZJS
1164 pam_code = pam_start(name, user, &conv, &handle);
1165 if (pam_code != PAM_SUCCESS) {
5b6319dc
LP
1166 handle = NULL;
1167 goto fail;
1168 }
1169
3cd24c1a
LP
1170 if (!tty) {
1171 _cleanup_free_ char *q = NULL;
1172
1173 /* Hmm, so no TTY was explicitly passed, but an fd passed to us directly might be a TTY. Let's figure
1174 * out if that's the case, and read the TTY off it. */
1175
1176 if (getttyname_malloc(STDIN_FILENO, &q) >= 0)
1177 tty = strjoina("/dev/", q);
1178 }
1179
f546241b
ZJS
1180 if (tty) {
1181 pam_code = pam_set_item(handle, PAM_TTY, tty);
1182 if (pam_code != PAM_SUCCESS)
5b6319dc 1183 goto fail;
f546241b 1184 }
5b6319dc 1185
84eada2f
JW
1186 STRV_FOREACH(nv, *env) {
1187 pam_code = pam_putenv(handle, *nv);
2065ca69
JW
1188 if (pam_code != PAM_SUCCESS)
1189 goto fail;
1190 }
1191
970edce6 1192 pam_code = pam_acct_mgmt(handle, flags);
f546241b 1193 if (pam_code != PAM_SUCCESS)
5b6319dc
LP
1194 goto fail;
1195
970edce6 1196 pam_code = pam_open_session(handle, flags);
f546241b 1197 if (pam_code != PAM_SUCCESS)
5b6319dc
LP
1198 goto fail;
1199
1200 close_session = true;
1201
f546241b
ZJS
1202 e = pam_getenvlist(handle);
1203 if (!e) {
5b6319dc
LP
1204 pam_code = PAM_BUF_ERR;
1205 goto fail;
1206 }
1207
1208 /* Block SIGTERM, so that we know that it won't get lost in
1209 * the child */
ce30c8dc 1210
72c0a2c2 1211 assert_se(sigprocmask_many(SIG_BLOCK, &old_ss, SIGTERM, -1) >= 0);
5b6319dc 1212
df0ff127 1213 parent_pid = getpid_cached();
5b6319dc 1214
4c253ed1
LP
1215 r = safe_fork("(sd-pam)", 0, &pam_pid);
1216 if (r < 0)
5b6319dc 1217 goto fail;
4c253ed1 1218 if (r == 0) {
7bb70b6e 1219 int sig, ret = EXIT_PAM;
5b6319dc
LP
1220
1221 /* The child's job is to reset the PAM session on
1222 * termination */
2d7c6aa2 1223 barrier_set_role(&barrier, BARRIER_CHILD);
5b6319dc 1224
4c253ed1
LP
1225 /* Make sure we don't keep open the passed fds in this child. We assume that otherwise only those fds
1226 * are open here that have been opened by PAM. */
1227 (void) close_many(fds, n_fds);
5b6319dc 1228
940c5210
AK
1229 /* Drop privileges - we don't need any to pam_close_session
1230 * and this will make PR_SET_PDEATHSIG work in most cases.
1231 * If this fails, ignore the error - but expect sd-pam threads
1232 * to fail to exit normally */
2d6fce8d 1233
97f0e76f
LP
1234 r = maybe_setgroups(0, NULL);
1235 if (r < 0)
1236 log_warning_errno(r, "Failed to setgroups() in sd-pam: %m");
2d6fce8d
LP
1237 if (setresgid(gid, gid, gid) < 0)
1238 log_warning_errno(errno, "Failed to setresgid() in sd-pam: %m");
940c5210 1239 if (setresuid(uid, uid, uid) < 0)
2d6fce8d 1240 log_warning_errno(errno, "Failed to setresuid() in sd-pam: %m");
940c5210 1241
ce30c8dc
LP
1242 (void) ignore_signals(SIGPIPE, -1);
1243
940c5210
AK
1244 /* Wait until our parent died. This will only work if
1245 * the above setresuid() succeeds, otherwise the kernel
1246 * will not allow unprivileged parents kill their privileged
1247 * children this way. We rely on the control groups kill logic
5b6319dc
LP
1248 * to do the rest for us. */
1249 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
1250 goto child_finish;
1251
2d7c6aa2
DH
1252 /* Tell the parent that our setup is done. This is especially
1253 * important regarding dropping privileges. Otherwise, unit
643f4706
ZJS
1254 * setup might race against our setresuid(2) call.
1255 *
1256 * If the parent aborted, we'll detect this below, hence ignore
1257 * return failure here. */
1258 (void) barrier_place(&barrier);
2d7c6aa2 1259
643f4706 1260 /* Check if our parent process might already have died? */
5b6319dc 1261 if (getppid() == parent_pid) {
d6e5f3ad
DM
1262 sigset_t ss;
1263
1264 assert_se(sigemptyset(&ss) >= 0);
1265 assert_se(sigaddset(&ss, SIGTERM) >= 0);
1266
3dead8d9
LP
1267 for (;;) {
1268 if (sigwait(&ss, &sig) < 0) {
1269 if (errno == EINTR)
1270 continue;
1271
1272 goto child_finish;
1273 }
5b6319dc 1274
3dead8d9
LP
1275 assert(sig == SIGTERM);
1276 break;
1277 }
5b6319dc
LP
1278 }
1279
3dead8d9 1280 /* If our parent died we'll end the session */
f546241b 1281 if (getppid() != parent_pid) {
970edce6 1282 pam_code = pam_close_session(handle, flags);
f546241b 1283 if (pam_code != PAM_SUCCESS)
5b6319dc 1284 goto child_finish;
f546241b 1285 }
5b6319dc 1286
7bb70b6e 1287 ret = 0;
5b6319dc
LP
1288
1289 child_finish:
970edce6 1290 pam_end(handle, pam_code | flags);
7bb70b6e 1291 _exit(ret);
5b6319dc
LP
1292 }
1293
2d7c6aa2
DH
1294 barrier_set_role(&barrier, BARRIER_PARENT);
1295
5b6319dc
LP
1296 /* If the child was forked off successfully it will do all the
1297 * cleanups, so forget about the handle here. */
1298 handle = NULL;
1299
3b8bddde 1300 /* Unblock SIGTERM again in the parent */
72c0a2c2 1301 assert_se(sigprocmask(SIG_SETMASK, &old_ss, NULL) >= 0);
5b6319dc
LP
1302
1303 /* We close the log explicitly here, since the PAM modules
1304 * might have opened it, but we don't want this fd around. */
1305 closelog();
1306
2d7c6aa2
DH
1307 /* Synchronously wait for the child to initialize. We don't care for
1308 * errors as we cannot recover. However, warn loudly if it happens. */
1309 if (!barrier_place_and_sync(&barrier))
1310 log_error("PAM initialization failed");
1311
130d3d22 1312 return strv_free_and_replace(*env, e);
5b6319dc
LP
1313
1314fail:
970edce6
ZJS
1315 if (pam_code != PAM_SUCCESS) {
1316 log_error("PAM failed: %s", pam_strerror(handle, pam_code));
7bb70b6e
LP
1317 r = -EPERM; /* PAM errors do not map to errno */
1318 } else
1319 log_error_errno(r, "PAM failed: %m");
9ba35398 1320
5b6319dc
LP
1321 if (handle) {
1322 if (close_session)
970edce6 1323 pam_code = pam_close_session(handle, flags);
5b6319dc 1324
970edce6 1325 pam_end(handle, pam_code | flags);
5b6319dc
LP
1326 }
1327
1328 strv_free(e);
5b6319dc
LP
1329 closelog();
1330
7bb70b6e 1331 return r;
cefc33ae
LP
1332#else
1333 return 0;
5b6319dc 1334#endif
cefc33ae 1335}
5b6319dc 1336
5d6b1584
LP
1337static void rename_process_from_path(const char *path) {
1338 char process_name[11];
1339 const char *p;
1340 size_t l;
1341
1342 /* This resulting string must fit in 10 chars (i.e. the length
1343 * of "/sbin/init") to look pretty in /bin/ps */
1344
2b6bf07d 1345 p = basename(path);
5d6b1584
LP
1346 if (isempty(p)) {
1347 rename_process("(...)");
1348 return;
1349 }
1350
1351 l = strlen(p);
1352 if (l > 8) {
1353 /* The end of the process name is usually more
1354 * interesting, since the first bit might just be
1355 * "systemd-" */
1356 p = p + l - 8;
1357 l = 8;
1358 }
1359
1360 process_name[0] = '(';
1361 memcpy(process_name+1, p, l);
1362 process_name[1+l] = ')';
1363 process_name[1+l+1] = 0;
1364
1365 rename_process(process_name);
1366}
1367
469830d1
LP
1368static bool context_has_address_families(const ExecContext *c) {
1369 assert(c);
1370
1371 return c->address_families_whitelist ||
1372 !set_isempty(c->address_families);
1373}
1374
1375static bool context_has_syscall_filters(const ExecContext *c) {
1376 assert(c);
1377
1378 return c->syscall_whitelist ||
8cfa775f 1379 !hashmap_isempty(c->syscall_filter);
469830d1
LP
1380}
1381
1382static bool context_has_no_new_privileges(const ExecContext *c) {
1383 assert(c);
1384
1385 if (c->no_new_privileges)
1386 return true;
1387
1388 if (have_effective_cap(CAP_SYS_ADMIN)) /* if we are privileged, we don't need NNP */
1389 return false;
1390
1391 /* We need NNP if we have any form of seccomp and are unprivileged */
1392 return context_has_address_families(c) ||
1393 c->memory_deny_write_execute ||
1394 c->restrict_realtime ||
f69567cb 1395 c->restrict_suid_sgid ||
469830d1
LP
1396 exec_context_restrict_namespaces_set(c) ||
1397 c->protect_kernel_tunables ||
1398 c->protect_kernel_modules ||
84703040 1399 c->protect_kernel_logs ||
469830d1
LP
1400 c->private_devices ||
1401 context_has_syscall_filters(c) ||
78e864e5 1402 !set_isempty(c->syscall_archs) ||
aecd5ac6
TM
1403 c->lock_personality ||
1404 c->protect_hostname;
469830d1
LP
1405}
1406
349cc4a5 1407#if HAVE_SECCOMP
17df7223 1408
83f12b27 1409static bool skip_seccomp_unavailable(const Unit* u, const char* msg) {
f673b62d
LP
1410
1411 if (is_seccomp_available())
1412 return false;
1413
f673b62d 1414 log_unit_debug(u, "SECCOMP features not detected in the kernel, skipping %s", msg);
f673b62d 1415 return true;
83f12b27
FS
1416}
1417
165a31c0 1418static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_ambient_hack) {
469830d1 1419 uint32_t negative_action, default_action, action;
165a31c0 1420 int r;
8351ceae 1421
469830d1 1422 assert(u);
c0467cf3 1423 assert(c);
8351ceae 1424
469830d1 1425 if (!context_has_syscall_filters(c))
83f12b27
FS
1426 return 0;
1427
469830d1
LP
1428 if (skip_seccomp_unavailable(u, "SystemCallFilter="))
1429 return 0;
e9642be2 1430
ccc16c78 1431 negative_action = c->syscall_errno == 0 ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno);
e9642be2 1432
469830d1
LP
1433 if (c->syscall_whitelist) {
1434 default_action = negative_action;
1435 action = SCMP_ACT_ALLOW;
7c66bae2 1436 } else {
469830d1
LP
1437 default_action = SCMP_ACT_ALLOW;
1438 action = negative_action;
57183d11 1439 }
8351ceae 1440
165a31c0
LP
1441 if (needs_ambient_hack) {
1442 r = seccomp_filter_set_add(c->syscall_filter, c->syscall_whitelist, syscall_filter_sets + SYSCALL_FILTER_SET_SETUID);
1443 if (r < 0)
1444 return r;
1445 }
1446
b54f36c6 1447 return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false);
4298d0b5
LP
1448}
1449
469830d1
LP
1450static int apply_syscall_archs(const Unit *u, const ExecContext *c) {
1451 assert(u);
4298d0b5
LP
1452 assert(c);
1453
469830d1 1454 if (set_isempty(c->syscall_archs))
83f12b27
FS
1455 return 0;
1456
469830d1
LP
1457 if (skip_seccomp_unavailable(u, "SystemCallArchitectures="))
1458 return 0;
4298d0b5 1459
469830d1
LP
1460 return seccomp_restrict_archs(c->syscall_archs);
1461}
4298d0b5 1462
469830d1
LP
1463static int apply_address_families(const Unit* u, const ExecContext *c) {
1464 assert(u);
1465 assert(c);
4298d0b5 1466
469830d1
LP
1467 if (!context_has_address_families(c))
1468 return 0;
4298d0b5 1469
469830d1
LP
1470 if (skip_seccomp_unavailable(u, "RestrictAddressFamilies="))
1471 return 0;
4298d0b5 1472
469830d1 1473 return seccomp_restrict_address_families(c->address_families, c->address_families_whitelist);
8351ceae 1474}
4298d0b5 1475
83f12b27 1476static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) {
469830d1 1477 assert(u);
f3e43635
TM
1478 assert(c);
1479
469830d1 1480 if (!c->memory_deny_write_execute)
83f12b27
FS
1481 return 0;
1482
469830d1
LP
1483 if (skip_seccomp_unavailable(u, "MemoryDenyWriteExecute="))
1484 return 0;
f3e43635 1485
469830d1 1486 return seccomp_memory_deny_write_execute();
f3e43635
TM
1487}
1488
83f12b27 1489static int apply_restrict_realtime(const Unit* u, const ExecContext *c) {
469830d1 1490 assert(u);
f4170c67
LP
1491 assert(c);
1492
469830d1 1493 if (!c->restrict_realtime)
83f12b27
FS
1494 return 0;
1495
469830d1
LP
1496 if (skip_seccomp_unavailable(u, "RestrictRealtime="))
1497 return 0;
f4170c67 1498
469830d1 1499 return seccomp_restrict_realtime();
f4170c67
LP
1500}
1501
f69567cb
LP
1502static int apply_restrict_suid_sgid(const Unit* u, const ExecContext *c) {
1503 assert(u);
1504 assert(c);
1505
1506 if (!c->restrict_suid_sgid)
1507 return 0;
1508
1509 if (skip_seccomp_unavailable(u, "RestrictSUIDSGID="))
1510 return 0;
1511
1512 return seccomp_restrict_suid_sgid();
1513}
1514
59e856c7 1515static int apply_protect_sysctl(const Unit *u, const ExecContext *c) {
469830d1 1516 assert(u);
59eeb84b
LP
1517 assert(c);
1518
1519 /* Turn off the legacy sysctl() system call. Many distributions turn this off while building the kernel, but
1520 * let's protect even those systems where this is left on in the kernel. */
1521
469830d1 1522 if (!c->protect_kernel_tunables)
59eeb84b
LP
1523 return 0;
1524
469830d1
LP
1525 if (skip_seccomp_unavailable(u, "ProtectKernelTunables="))
1526 return 0;
59eeb84b 1527
469830d1 1528 return seccomp_protect_sysctl();
59eeb84b
LP
1529}
1530
59e856c7 1531static int apply_protect_kernel_modules(const Unit *u, const ExecContext *c) {
469830d1 1532 assert(u);
502d704e
DH
1533 assert(c);
1534
25a8d8a0 1535 /* Turn off module syscalls on ProtectKernelModules=yes */
502d704e 1536
469830d1
LP
1537 if (!c->protect_kernel_modules)
1538 return 0;
1539
502d704e
DH
1540 if (skip_seccomp_unavailable(u, "ProtectKernelModules="))
1541 return 0;
1542
b54f36c6 1543 return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM), false);
502d704e
DH
1544}
1545
84703040
KK
1546static int apply_protect_kernel_logs(const Unit *u, const ExecContext *c) {
1547 assert(u);
1548 assert(c);
1549
1550 if (!c->protect_kernel_logs)
1551 return 0;
1552
1553 if (skip_seccomp_unavailable(u, "ProtectKernelLogs="))
1554 return 0;
1555
1556 return seccomp_protect_syslog();
1557}
1558
59e856c7 1559static int apply_private_devices(const Unit *u, const ExecContext *c) {
469830d1 1560 assert(u);
ba128bb8
LP
1561 assert(c);
1562
8f81a5f6 1563 /* If PrivateDevices= is set, also turn off iopl and all @raw-io syscalls. */
ba128bb8 1564
469830d1
LP
1565 if (!c->private_devices)
1566 return 0;
1567
ba128bb8
LP
1568 if (skip_seccomp_unavailable(u, "PrivateDevices="))
1569 return 0;
1570
b54f36c6 1571 return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM), false);
ba128bb8
LP
1572}
1573
34cf6c43 1574static int apply_restrict_namespaces(const Unit *u, const ExecContext *c) {
469830d1 1575 assert(u);
add00535
LP
1576 assert(c);
1577
1578 if (!exec_context_restrict_namespaces_set(c))
1579 return 0;
1580
1581 if (skip_seccomp_unavailable(u, "RestrictNamespaces="))
1582 return 0;
1583
1584 return seccomp_restrict_namespaces(c->restrict_namespaces);
1585}
1586
78e864e5 1587static int apply_lock_personality(const Unit* u, const ExecContext *c) {
e8132d63
LP
1588 unsigned long personality;
1589 int r;
78e864e5
TM
1590
1591 assert(u);
1592 assert(c);
1593
1594 if (!c->lock_personality)
1595 return 0;
1596
1597 if (skip_seccomp_unavailable(u, "LockPersonality="))
1598 return 0;
1599
e8132d63
LP
1600 personality = c->personality;
1601
1602 /* If personality is not specified, use either PER_LINUX or PER_LINUX32 depending on what is currently set. */
1603 if (personality == PERSONALITY_INVALID) {
1604
1605 r = opinionated_personality(&personality);
1606 if (r < 0)
1607 return r;
1608 }
78e864e5
TM
1609
1610 return seccomp_lock_personality(personality);
1611}
1612
c0467cf3 1613#endif
8351ceae 1614
3042bbeb 1615static void do_idle_pipe_dance(int idle_pipe[static 4]) {
31a7eb86
ZJS
1616 assert(idle_pipe);
1617
54eb2300
LP
1618 idle_pipe[1] = safe_close(idle_pipe[1]);
1619 idle_pipe[2] = safe_close(idle_pipe[2]);
31a7eb86
ZJS
1620
1621 if (idle_pipe[0] >= 0) {
1622 int r;
1623
1624 r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
1625
1626 if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
c7cc737f
LP
1627 ssize_t n;
1628
31a7eb86 1629 /* Signal systemd that we are bored and want to continue. */
c7cc737f
LP
1630 n = write(idle_pipe[3], "x", 1);
1631 if (n > 0)
cd972d69 1632 /* Wait for systemd to react to the signal above. */
54756dce 1633 (void) fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
31a7eb86
ZJS
1634 }
1635
54eb2300 1636 idle_pipe[0] = safe_close(idle_pipe[0]);
31a7eb86
ZJS
1637
1638 }
1639
54eb2300 1640 idle_pipe[3] = safe_close(idle_pipe[3]);
31a7eb86
ZJS
1641}
1642
fb2042dd
YW
1643static const char *exec_directory_env_name_to_string(ExecDirectoryType t);
1644
7cae38c4 1645static int build_environment(
34cf6c43 1646 const Unit *u,
9fa95f85 1647 const ExecContext *c,
1e22b5cd 1648 const ExecParameters *p,
da6053d0 1649 size_t n_fds,
7cae38c4
LP
1650 const char *home,
1651 const char *username,
1652 const char *shell,
7bce046b
LP
1653 dev_t journal_stream_dev,
1654 ino_t journal_stream_ino,
7cae38c4
LP
1655 char ***ret) {
1656
1657 _cleanup_strv_free_ char **our_env = NULL;
fb2042dd 1658 ExecDirectoryType t;
da6053d0 1659 size_t n_env = 0;
7cae38c4
LP
1660 char *x;
1661
4b58153d 1662 assert(u);
7cae38c4 1663 assert(c);
7c1cb6f1 1664 assert(p);
7cae38c4
LP
1665 assert(ret);
1666
fb2042dd 1667 our_env = new0(char*, 14 + _EXEC_DIRECTORY_TYPE_MAX);
7cae38c4
LP
1668 if (!our_env)
1669 return -ENOMEM;
1670
1671 if (n_fds > 0) {
8dd4c05b
LP
1672 _cleanup_free_ char *joined = NULL;
1673
df0ff127 1674 if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid_cached()) < 0)
7cae38c4
LP
1675 return -ENOMEM;
1676 our_env[n_env++] = x;
1677
da6053d0 1678 if (asprintf(&x, "LISTEN_FDS=%zu", n_fds) < 0)
7cae38c4
LP
1679 return -ENOMEM;
1680 our_env[n_env++] = x;
8dd4c05b 1681
1e22b5cd 1682 joined = strv_join(p->fd_names, ":");
8dd4c05b
LP
1683 if (!joined)
1684 return -ENOMEM;
1685
605405c6 1686 x = strjoin("LISTEN_FDNAMES=", joined);
8dd4c05b
LP
1687 if (!x)
1688 return -ENOMEM;
1689 our_env[n_env++] = x;
7cae38c4
LP
1690 }
1691
b08af3b1 1692 if ((p->flags & EXEC_SET_WATCHDOG) && p->watchdog_usec > 0) {
df0ff127 1693 if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid_cached()) < 0)
09812eb7
LP
1694 return -ENOMEM;
1695 our_env[n_env++] = x;
1696
1e22b5cd 1697 if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, p->watchdog_usec) < 0)
09812eb7
LP
1698 return -ENOMEM;
1699 our_env[n_env++] = x;
1700 }
1701
fd63e712
LP
1702 /* If this is D-Bus, tell the nss-systemd module, since it relies on being able to use D-Bus look up dynamic
1703 * users via PID 1, possibly dead-locking the dbus daemon. This way it will not use D-Bus to resolve names, but
1704 * check the database directly. */
ac647978 1705 if (p->flags & EXEC_NSS_BYPASS_BUS) {
fd63e712
LP
1706 x = strdup("SYSTEMD_NSS_BYPASS_BUS=1");
1707 if (!x)
1708 return -ENOMEM;
1709 our_env[n_env++] = x;
1710 }
1711
7cae38c4 1712 if (home) {
b910cc72 1713 x = strjoin("HOME=", home);
7cae38c4
LP
1714 if (!x)
1715 return -ENOMEM;
7bbead1d
LP
1716
1717 path_simplify(x + 5, true);
7cae38c4
LP
1718 our_env[n_env++] = x;
1719 }
1720
1721 if (username) {
b910cc72 1722 x = strjoin("LOGNAME=", username);
7cae38c4
LP
1723 if (!x)
1724 return -ENOMEM;
1725 our_env[n_env++] = x;
1726
b910cc72 1727 x = strjoin("USER=", username);
7cae38c4
LP
1728 if (!x)
1729 return -ENOMEM;
1730 our_env[n_env++] = x;
1731 }
1732
1733 if (shell) {
b910cc72 1734 x = strjoin("SHELL=", shell);
7cae38c4
LP
1735 if (!x)
1736 return -ENOMEM;
7bbead1d
LP
1737
1738 path_simplify(x + 6, true);
7cae38c4
LP
1739 our_env[n_env++] = x;
1740 }
1741
4b58153d
LP
1742 if (!sd_id128_is_null(u->invocation_id)) {
1743 if (asprintf(&x, "INVOCATION_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id)) < 0)
1744 return -ENOMEM;
1745
1746 our_env[n_env++] = x;
1747 }
1748
6af760f3
LP
1749 if (exec_context_needs_term(c)) {
1750 const char *tty_path, *term = NULL;
1751
1752 tty_path = exec_context_tty_path(c);
1753
1754 /* If we are forked off PID 1 and we are supposed to operate on /dev/console, then let's try to inherit
1755 * the $TERM set for PID 1. This is useful for containers so that the $TERM the container manager
1756 * passes to PID 1 ends up all the way in the console login shown. */
1757
1758 if (path_equal(tty_path, "/dev/console") && getppid() == 1)
1759 term = getenv("TERM");
1760 if (!term)
1761 term = default_term_for_tty(tty_path);
7cae38c4 1762
b910cc72 1763 x = strjoin("TERM=", term);
7cae38c4
LP
1764 if (!x)
1765 return -ENOMEM;
1766 our_env[n_env++] = x;
1767 }
1768
7bce046b
LP
1769 if (journal_stream_dev != 0 && journal_stream_ino != 0) {
1770 if (asprintf(&x, "JOURNAL_STREAM=" DEV_FMT ":" INO_FMT, journal_stream_dev, journal_stream_ino) < 0)
1771 return -ENOMEM;
1772
1773 our_env[n_env++] = x;
1774 }
1775
fb2042dd
YW
1776 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
1777 _cleanup_free_ char *pre = NULL, *joined = NULL;
1778 const char *n;
1779
1780 if (!p->prefix[t])
1781 continue;
1782
1783 if (strv_isempty(c->directories[t].paths))
1784 continue;
1785
1786 n = exec_directory_env_name_to_string(t);
1787 if (!n)
1788 continue;
1789
1790 pre = strjoin(p->prefix[t], "/");
1791 if (!pre)
1792 return -ENOMEM;
1793
1794 joined = strv_join_prefix(c->directories[t].paths, ":", pre);
1795 if (!joined)
1796 return -ENOMEM;
1797
1798 x = strjoin(n, "=", joined);
1799 if (!x)
1800 return -ENOMEM;
1801
1802 our_env[n_env++] = x;
1803 }
1804
7cae38c4 1805 our_env[n_env++] = NULL;
fb2042dd 1806 assert(n_env <= 14 + _EXEC_DIRECTORY_TYPE_MAX);
7cae38c4 1807
ae2a15bc 1808 *ret = TAKE_PTR(our_env);
7cae38c4
LP
1809
1810 return 0;
1811}
1812
b4c14404
FB
1813static int build_pass_environment(const ExecContext *c, char ***ret) {
1814 _cleanup_strv_free_ char **pass_env = NULL;
1815 size_t n_env = 0, n_bufsize = 0;
1816 char **i;
1817
1818 STRV_FOREACH(i, c->pass_environment) {
1819 _cleanup_free_ char *x = NULL;
1820 char *v;
1821
1822 v = getenv(*i);
1823 if (!v)
1824 continue;
605405c6 1825 x = strjoin(*i, "=", v);
b4c14404
FB
1826 if (!x)
1827 return -ENOMEM;
00819cc1 1828
b4c14404
FB
1829 if (!GREEDY_REALLOC(pass_env, n_bufsize, n_env + 2))
1830 return -ENOMEM;
00819cc1 1831
1cc6c93a 1832 pass_env[n_env++] = TAKE_PTR(x);
b4c14404 1833 pass_env[n_env] = NULL;
b4c14404
FB
1834 }
1835
ae2a15bc 1836 *ret = TAKE_PTR(pass_env);
b4c14404
FB
1837
1838 return 0;
1839}
1840
8b44a3d2
LP
1841static bool exec_needs_mount_namespace(
1842 const ExecContext *context,
1843 const ExecParameters *params,
4657abb5 1844 const ExecRuntime *runtime) {
8b44a3d2
LP
1845
1846 assert(context);
1847 assert(params);
1848
915e6d16
LP
1849 if (context->root_image)
1850 return true;
1851
2a624c36
AP
1852 if (!strv_isempty(context->read_write_paths) ||
1853 !strv_isempty(context->read_only_paths) ||
1854 !strv_isempty(context->inaccessible_paths))
8b44a3d2
LP
1855 return true;
1856
42b1d8e0 1857 if (context->n_bind_mounts > 0)
d2d6c096
LP
1858 return true;
1859
2abd4e38
YW
1860 if (context->n_temporary_filesystems > 0)
1861 return true;
1862
37ed15d7 1863 if (!IN_SET(context->mount_flags, 0, MS_SHARED))
8b44a3d2
LP
1864 return true;
1865
1866 if (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir))
1867 return true;
1868
8b44a3d2 1869 if (context->private_devices ||
228af36f 1870 context->private_mounts ||
8b44a3d2 1871 context->protect_system != PROTECT_SYSTEM_NO ||
59eeb84b
LP
1872 context->protect_home != PROTECT_HOME_NO ||
1873 context->protect_kernel_tunables ||
c575770b 1874 context->protect_kernel_modules ||
59eeb84b 1875 context->protect_control_groups)
8b44a3d2
LP
1876 return true;
1877
37c56f89
YW
1878 if (context->root_directory) {
1879 ExecDirectoryType t;
1880
1881 if (context->mount_apivfs)
1882 return true;
1883
1884 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
1885 if (!params->prefix[t])
1886 continue;
1887
1888 if (!strv_isempty(context->directories[t].paths))
1889 return true;
1890 }
1891 }
5d997827 1892
42b1d8e0 1893 if (context->dynamic_user &&
b43ee82f 1894 (!strv_isempty(context->directories[EXEC_DIRECTORY_STATE].paths) ||
42b1d8e0
YW
1895 !strv_isempty(context->directories[EXEC_DIRECTORY_CACHE].paths) ||
1896 !strv_isempty(context->directories[EXEC_DIRECTORY_LOGS].paths)))
1897 return true;
1898
8b44a3d2
LP
1899 return false;
1900}
1901
d251207d
LP
1902static int setup_private_users(uid_t uid, gid_t gid) {
1903 _cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
1904 _cleanup_close_pair_ int errno_pipe[2] = { -1, -1 };
1905 _cleanup_close_ int unshare_ready_fd = -1;
1906 _cleanup_(sigkill_waitp) pid_t pid = 0;
1907 uint64_t c = 1;
d251207d
LP
1908 ssize_t n;
1909 int r;
1910
1911 /* Set up a user namespace and map root to root, the selected UID/GID to itself, and everything else to
1912 * nobody. In order to be able to write this mapping we need CAP_SETUID in the original user namespace, which
1913 * we however lack after opening the user namespace. To work around this we fork() a temporary child process,
1914 * which waits for the parent to create the new user namespace while staying in the original namespace. The
1915 * child then writes the UID mapping, under full privileges. The parent waits for the child to finish and
1916 * continues execution normally. */
1917
587ab01b
ZJS
1918 if (uid != 0 && uid_is_valid(uid)) {
1919 r = asprintf(&uid_map,
1920 "0 0 1\n" /* Map root → root */
1921 UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */
1922 uid, uid);
1923 if (r < 0)
1924 return -ENOMEM;
1925 } else {
e0f3720e 1926 uid_map = strdup("0 0 1\n"); /* The case where the above is the same */
587ab01b
ZJS
1927 if (!uid_map)
1928 return -ENOMEM;
1929 }
d251207d 1930
587ab01b
ZJS
1931 if (gid != 0 && gid_is_valid(gid)) {
1932 r = asprintf(&gid_map,
1933 "0 0 1\n" /* Map root → root */
1934 GID_FMT " " GID_FMT " 1\n", /* Map $GID → $GID */
1935 gid, gid);
1936 if (r < 0)
1937 return -ENOMEM;
1938 } else {
d251207d 1939 gid_map = strdup("0 0 1\n"); /* The case where the above is the same */
587ab01b
ZJS
1940 if (!gid_map)
1941 return -ENOMEM;
1942 }
d251207d
LP
1943
1944 /* Create a communication channel so that the parent can tell the child when it finished creating the user
1945 * namespace. */
1946 unshare_ready_fd = eventfd(0, EFD_CLOEXEC);
1947 if (unshare_ready_fd < 0)
1948 return -errno;
1949
1950 /* Create a communication channel so that the child can tell the parent a proper error code in case it
1951 * failed. */
1952 if (pipe2(errno_pipe, O_CLOEXEC) < 0)
1953 return -errno;
1954
4c253ed1
LP
1955 r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
1956 if (r < 0)
1957 return r;
1958 if (r == 0) {
d251207d
LP
1959 _cleanup_close_ int fd = -1;
1960 const char *a;
1961 pid_t ppid;
1962
1963 /* Child process, running in the original user namespace. Let's update the parent's UID/GID map from
1964 * here, after the parent opened its own user namespace. */
1965
1966 ppid = getppid();
1967 errno_pipe[0] = safe_close(errno_pipe[0]);
1968
1969 /* Wait until the parent unshared the user namespace */
1970 if (read(unshare_ready_fd, &c, sizeof(c)) < 0) {
1971 r = -errno;
1972 goto child_fail;
1973 }
1974
1975 /* Disable the setgroups() system call in the child user namespace, for good. */
1976 a = procfs_file_alloca(ppid, "setgroups");
1977 fd = open(a, O_WRONLY|O_CLOEXEC);
1978 if (fd < 0) {
1979 if (errno != ENOENT) {
1980 r = -errno;
1981 goto child_fail;
1982 }
1983
1984 /* If the file is missing the kernel is too old, let's continue anyway. */
1985 } else {
1986 if (write(fd, "deny\n", 5) < 0) {
1987 r = -errno;
1988 goto child_fail;
1989 }
1990
1991 fd = safe_close(fd);
1992 }
1993
1994 /* First write the GID map */
1995 a = procfs_file_alloca(ppid, "gid_map");
1996 fd = open(a, O_WRONLY|O_CLOEXEC);
1997 if (fd < 0) {
1998 r = -errno;
1999 goto child_fail;
2000 }
2001 if (write(fd, gid_map, strlen(gid_map)) < 0) {
2002 r = -errno;
2003 goto child_fail;
2004 }
2005 fd = safe_close(fd);
2006
2007 /* The write the UID map */
2008 a = procfs_file_alloca(ppid, "uid_map");
2009 fd = open(a, O_WRONLY|O_CLOEXEC);
2010 if (fd < 0) {
2011 r = -errno;
2012 goto child_fail;
2013 }
2014 if (write(fd, uid_map, strlen(uid_map)) < 0) {
2015 r = -errno;
2016 goto child_fail;
2017 }
2018
2019 _exit(EXIT_SUCCESS);
2020
2021 child_fail:
2022 (void) write(errno_pipe[1], &r, sizeof(r));
2023 _exit(EXIT_FAILURE);
2024 }
2025
2026 errno_pipe[1] = safe_close(errno_pipe[1]);
2027
2028 if (unshare(CLONE_NEWUSER) < 0)
2029 return -errno;
2030
2031 /* Let the child know that the namespace is ready now */
2032 if (write(unshare_ready_fd, &c, sizeof(c)) < 0)
2033 return -errno;
2034
2035 /* Try to read an error code from the child */
2036 n = read(errno_pipe[0], &r, sizeof(r));
2037 if (n < 0)
2038 return -errno;
2039 if (n == sizeof(r)) { /* an error code was sent to us */
2040 if (r < 0)
2041 return r;
2042 return -EIO;
2043 }
2044 if (n != 0) /* on success we should have read 0 bytes */
2045 return -EIO;
2046
2e87a1fd
LP
2047 r = wait_for_terminate_and_check("(sd-userns)", pid, 0);
2048 pid = 0;
d251207d
LP
2049 if (r < 0)
2050 return r;
2e87a1fd 2051 if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */
d251207d
LP
2052 return -EIO;
2053
2054 return 0;
2055}
2056
494d0247
YW
2057static bool exec_directory_is_private(const ExecContext *context, ExecDirectoryType type) {
2058 if (!context->dynamic_user)
2059 return false;
2060
2061 if (type == EXEC_DIRECTORY_CONFIGURATION)
2062 return false;
2063
2064 if (type == EXEC_DIRECTORY_RUNTIME && context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO)
2065 return false;
2066
2067 return true;
2068}
2069
3536f49e 2070static int setup_exec_directory(
07689d5d
LP
2071 const ExecContext *context,
2072 const ExecParameters *params,
2073 uid_t uid,
3536f49e 2074 gid_t gid,
3536f49e
YW
2075 ExecDirectoryType type,
2076 int *exit_status) {
07689d5d 2077
72fd1768 2078 static const int exit_status_table[_EXEC_DIRECTORY_TYPE_MAX] = {
3536f49e
YW
2079 [EXEC_DIRECTORY_RUNTIME] = EXIT_RUNTIME_DIRECTORY,
2080 [EXEC_DIRECTORY_STATE] = EXIT_STATE_DIRECTORY,
2081 [EXEC_DIRECTORY_CACHE] = EXIT_CACHE_DIRECTORY,
2082 [EXEC_DIRECTORY_LOGS] = EXIT_LOGS_DIRECTORY,
2083 [EXEC_DIRECTORY_CONFIGURATION] = EXIT_CONFIGURATION_DIRECTORY,
2084 };
07689d5d
LP
2085 char **rt;
2086 int r;
2087
2088 assert(context);
2089 assert(params);
72fd1768 2090 assert(type >= 0 && type < _EXEC_DIRECTORY_TYPE_MAX);
3536f49e 2091 assert(exit_status);
07689d5d 2092
3536f49e
YW
2093 if (!params->prefix[type])
2094 return 0;
2095
8679efde 2096 if (params->flags & EXEC_CHOWN_DIRECTORIES) {
3536f49e
YW
2097 if (!uid_is_valid(uid))
2098 uid = 0;
2099 if (!gid_is_valid(gid))
2100 gid = 0;
2101 }
2102
2103 STRV_FOREACH(rt, context->directories[type].paths) {
6c47cd7d 2104 _cleanup_free_ char *p = NULL, *pp = NULL;
07689d5d 2105
edbfeb12 2106 p = path_join(params->prefix[type], *rt);
3536f49e
YW
2107 if (!p) {
2108 r = -ENOMEM;
2109 goto fail;
2110 }
07689d5d 2111
23a7448e
YW
2112 r = mkdir_parents_label(p, 0755);
2113 if (r < 0)
3536f49e 2114 goto fail;
23a7448e 2115
494d0247 2116 if (exec_directory_is_private(context, type)) {
6c9c51e5 2117 _cleanup_free_ char *private_root = NULL;
6c47cd7d 2118
3f5b1508
LP
2119 /* So, here's one extra complication when dealing with DynamicUser=1 units. In that
2120 * case we want to avoid leaving a directory around fully accessible that is owned by
2121 * a dynamic user whose UID is later on reused. To lock this down we use the same
2122 * trick used by container managers to prohibit host users to get access to files of
2123 * the same UID in containers: we place everything inside a directory that has an
2124 * access mode of 0700 and is owned root:root, so that it acts as security boundary
2125 * for unprivileged host code. We then use fs namespacing to make this directory
2126 * permeable for the service itself.
6c47cd7d 2127 *
3f5b1508
LP
2128 * Specifically: for a service which wants a special directory "foo/" we first create
2129 * a directory "private/" with access mode 0700 owned by root:root. Then we place
2130 * "foo" inside of that directory (i.e. "private/foo/"), and make "foo" a symlink to
2131 * "private/foo". This way, privileged host users can access "foo/" as usual, but
2132 * unprivileged host users can't look into it. Inside of the namespace of the unit
2133 * "private/" is replaced by a more liberally accessible tmpfs, into which the host's
2134 * "private/foo/" is mounted under the same name, thus disabling the access boundary
2135 * for the service and making sure it only gets access to the dirs it needs but no
2136 * others. Tricky? Yes, absolutely, but it works!
6c47cd7d 2137 *
3f5b1508
LP
2138 * Note that we don't do this for EXEC_DIRECTORY_CONFIGURATION as that's assumed not
2139 * to be owned by the service itself.
2140 *
2141 * Also, note that we don't do this for EXEC_DIRECTORY_RUNTIME as that's often used
2142 * for sharing files or sockets with other services. */
6c47cd7d 2143
edbfeb12 2144 private_root = path_join(params->prefix[type], "private");
6c47cd7d
LP
2145 if (!private_root) {
2146 r = -ENOMEM;
2147 goto fail;
2148 }
2149
2150 /* First set up private root if it doesn't exist yet, with access mode 0700 and owned by root:root */
37c1d5e9 2151 r = mkdir_safe_label(private_root, 0700, 0, 0, MKDIR_WARN_MODE);
6c47cd7d
LP
2152 if (r < 0)
2153 goto fail;
2154
edbfeb12 2155 pp = path_join(private_root, *rt);
6c47cd7d
LP
2156 if (!pp) {
2157 r = -ENOMEM;
2158 goto fail;
2159 }
2160
2161 /* Create all directories between the configured directory and this private root, and mark them 0755 */
2162 r = mkdir_parents_label(pp, 0755);
2163 if (r < 0)
2164 goto fail;
2165
949befd3
LP
2166 if (is_dir(p, false) > 0 &&
2167 (laccess(pp, F_OK) < 0 && errno == ENOENT)) {
2168
2169 /* Hmm, the private directory doesn't exist yet, but the normal one exists? If so, move
2170 * it over. Most likely the service has been upgraded from one that didn't use
2171 * DynamicUser=1, to one that does. */
2172
cf52c45d
LP
2173 log_info("Found pre-existing public %s= directory %s, migrating to %s.\n"
2174 "Apparently, service previously had DynamicUser= turned off, and has now turned it on.",
2175 exec_directory_type_to_string(type), p, pp);
2176
949befd3
LP
2177 if (rename(p, pp) < 0) {
2178 r = -errno;
2179 goto fail;
2180 }
2181 } else {
2182 /* Otherwise, create the actual directory for the service */
2183
2184 r = mkdir_label(pp, context->directories[type].mode);
2185 if (r < 0 && r != -EEXIST)
2186 goto fail;
2187 }
6c47cd7d 2188
6c47cd7d 2189 /* And link it up from the original place */
6c9c51e5 2190 r = symlink_idempotent(pp, p, true);
6c47cd7d
LP
2191 if (r < 0)
2192 goto fail;
2193
6c47cd7d 2194 } else {
5c6d40d1
LP
2195 _cleanup_free_ char *target = NULL;
2196
2197 if (type != EXEC_DIRECTORY_CONFIGURATION &&
2198 readlink_and_make_absolute(p, &target) >= 0) {
2199 _cleanup_free_ char *q = NULL;
2200
2201 /* This already exists and is a symlink? Interesting. Maybe it's one created
2193f17c
LP
2202 * by DynamicUser=1 (see above)?
2203 *
2204 * We do this for all directory types except for ConfigurationDirectory=,
2205 * since they all support the private/ symlink logic at least in some
2206 * configurations, see above. */
5c6d40d1
LP
2207
2208 q = path_join(params->prefix[type], "private", *rt);
2209 if (!q) {
2210 r = -ENOMEM;
2211 goto fail;
2212 }
2213
2214 if (path_equal(q, target)) {
2215
2216 /* Hmm, apparently DynamicUser= was once turned on for this service,
2217 * but is no longer. Let's move the directory back up. */
2218
cf52c45d
LP
2219 log_info("Found pre-existing private %s= directory %s, migrating to %s.\n"
2220 "Apparently, service previously had DynamicUser= turned on, and has now turned it off.",
2221 exec_directory_type_to_string(type), q, p);
2222
5c6d40d1
LP
2223 if (unlink(p) < 0) {
2224 r = -errno;
2225 goto fail;
2226 }
2227
2228 if (rename(q, p) < 0) {
2229 r = -errno;
2230 goto fail;
2231 }
2232 }
2233 }
2234
6c47cd7d 2235 r = mkdir_label(p, context->directories[type].mode);
d484580c 2236 if (r < 0) {
d484580c
LP
2237 if (r != -EEXIST)
2238 goto fail;
2239
206e9864
LP
2240 if (type == EXEC_DIRECTORY_CONFIGURATION) {
2241 struct stat st;
2242
2243 /* Don't change the owner/access mode of the configuration directory,
2244 * as in the common case it is not written to by a service, and shall
2245 * not be writable. */
2246
2247 if (stat(p, &st) < 0) {
2248 r = -errno;
2249 goto fail;
2250 }
2251
2252 /* Still complain if the access mode doesn't match */
2253 if (((st.st_mode ^ context->directories[type].mode) & 07777) != 0)
2254 log_warning("%s \'%s\' already exists but the mode is different. "
2255 "(File system: %o %sMode: %o)",
2256 exec_directory_type_to_string(type), *rt,
2257 st.st_mode & 07777, exec_directory_type_to_string(type), context->directories[type].mode & 07777);
2258
6cff72eb 2259 continue;
206e9864 2260 }
6cff72eb 2261 }
a1164ae3 2262 }
07689d5d 2263
206e9864 2264 /* Lock down the access mode (we use chmod_and_chown() to make this idempotent. We don't
5238e957 2265 * specify UID/GID here, so that path_chown_recursive() can optimize things depending on the
206e9864
LP
2266 * current UID/GID ownership.) */
2267 r = chmod_and_chown(pp ?: p, context->directories[type].mode, UID_INVALID, GID_INVALID);
2268 if (r < 0)
2269 goto fail;
c71b2eb7 2270
607b358e
LP
2271 /* Then, change the ownership of the whole tree, if necessary. When dynamic users are used we
2272 * drop the suid/sgid bits, since we really don't want SUID/SGID files for dynamic UID/GID
2273 * assignments to exist.*/
2274 r = path_chown_recursive(pp ?: p, uid, gid, context->dynamic_user ? 01777 : 07777);
07689d5d 2275 if (r < 0)
3536f49e 2276 goto fail;
07689d5d
LP
2277 }
2278
2279 return 0;
3536f49e
YW
2280
2281fail:
2282 *exit_status = exit_status_table[type];
3536f49e 2283 return r;
07689d5d
LP
2284}
2285
92b423b9 2286#if ENABLE_SMACK
cefc33ae
LP
2287static int setup_smack(
2288 const ExecContext *context,
2289 const ExecCommand *command) {
2290
cefc33ae
LP
2291 int r;
2292
2293 assert(context);
2294 assert(command);
2295
cefc33ae
LP
2296 if (context->smack_process_label) {
2297 r = mac_smack_apply_pid(0, context->smack_process_label);
2298 if (r < 0)
2299 return r;
2300 }
2301#ifdef SMACK_DEFAULT_PROCESS_LABEL
2302 else {
2303 _cleanup_free_ char *exec_label = NULL;
2304
2305 r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label);
4c701096 2306 if (r < 0 && !IN_SET(r, -ENODATA, -EOPNOTSUPP))
cefc33ae
LP
2307 return r;
2308
2309 r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL);
2310 if (r < 0)
2311 return r;
2312 }
cefc33ae
LP
2313#endif
2314
2315 return 0;
2316}
92b423b9 2317#endif
cefc33ae 2318
6c47cd7d
LP
2319static int compile_bind_mounts(
2320 const ExecContext *context,
2321 const ExecParameters *params,
2322 BindMount **ret_bind_mounts,
da6053d0 2323 size_t *ret_n_bind_mounts,
6c47cd7d
LP
2324 char ***ret_empty_directories) {
2325
2326 _cleanup_strv_free_ char **empty_directories = NULL;
2327 BindMount *bind_mounts;
da6053d0 2328 size_t n, h = 0, i;
6c47cd7d
LP
2329 ExecDirectoryType t;
2330 int r;
2331
2332 assert(context);
2333 assert(params);
2334 assert(ret_bind_mounts);
2335 assert(ret_n_bind_mounts);
2336 assert(ret_empty_directories);
2337
2338 n = context->n_bind_mounts;
2339 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
2340 if (!params->prefix[t])
2341 continue;
2342
2343 n += strv_length(context->directories[t].paths);
2344 }
2345
2346 if (n <= 0) {
2347 *ret_bind_mounts = NULL;
2348 *ret_n_bind_mounts = 0;
2349 *ret_empty_directories = NULL;
2350 return 0;
2351 }
2352
2353 bind_mounts = new(BindMount, n);
2354 if (!bind_mounts)
2355 return -ENOMEM;
2356
a8cabc61 2357 for (i = 0; i < context->n_bind_mounts; i++) {
6c47cd7d
LP
2358 BindMount *item = context->bind_mounts + i;
2359 char *s, *d;
2360
2361 s = strdup(item->source);
2362 if (!s) {
2363 r = -ENOMEM;
2364 goto finish;
2365 }
2366
2367 d = strdup(item->destination);
2368 if (!d) {
2369 free(s);
2370 r = -ENOMEM;
2371 goto finish;
2372 }
2373
2374 bind_mounts[h++] = (BindMount) {
2375 .source = s,
2376 .destination = d,
2377 .read_only = item->read_only,
2378 .recursive = item->recursive,
2379 .ignore_enoent = item->ignore_enoent,
2380 };
2381 }
2382
2383 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
2384 char **suffix;
2385
2386 if (!params->prefix[t])
2387 continue;
2388
2389 if (strv_isempty(context->directories[t].paths))
2390 continue;
2391
494d0247 2392 if (exec_directory_is_private(context, t) &&
5609f688 2393 !(context->root_directory || context->root_image)) {
6c47cd7d
LP
2394 char *private_root;
2395
2396 /* So this is for a dynamic user, and we need to make sure the process can access its own
2397 * directory. For that we overmount the usually inaccessible "private" subdirectory with a
2398 * tmpfs that makes it accessible and is empty except for the submounts we do this for. */
2399
657ee2d8 2400 private_root = path_join(params->prefix[t], "private");
6c47cd7d
LP
2401 if (!private_root) {
2402 r = -ENOMEM;
2403 goto finish;
2404 }
2405
2406 r = strv_consume(&empty_directories, private_root);
a635a7ae 2407 if (r < 0)
6c47cd7d 2408 goto finish;
6c47cd7d
LP
2409 }
2410
2411 STRV_FOREACH(suffix, context->directories[t].paths) {
2412 char *s, *d;
2413
494d0247 2414 if (exec_directory_is_private(context, t))
657ee2d8 2415 s = path_join(params->prefix[t], "private", *suffix);
6c47cd7d 2416 else
657ee2d8 2417 s = path_join(params->prefix[t], *suffix);
6c47cd7d
LP
2418 if (!s) {
2419 r = -ENOMEM;
2420 goto finish;
2421 }
2422
494d0247 2423 if (exec_directory_is_private(context, t) &&
5609f688
YW
2424 (context->root_directory || context->root_image))
2425 /* When RootDirectory= or RootImage= are set, then the symbolic link to the private
2426 * directory is not created on the root directory. So, let's bind-mount the directory
2427 * on the 'non-private' place. */
657ee2d8 2428 d = path_join(params->prefix[t], *suffix);
5609f688
YW
2429 else
2430 d = strdup(s);
6c47cd7d
LP
2431 if (!d) {
2432 free(s);
2433 r = -ENOMEM;
2434 goto finish;
2435 }
2436
2437 bind_mounts[h++] = (BindMount) {
2438 .source = s,
2439 .destination = d,
2440 .read_only = false,
9ce4e4b0 2441 .nosuid = context->dynamic_user, /* don't allow suid/sgid when DynamicUser= is on */
6c47cd7d
LP
2442 .recursive = true,
2443 .ignore_enoent = false,
2444 };
2445 }
2446 }
2447
2448 assert(h == n);
2449
2450 *ret_bind_mounts = bind_mounts;
2451 *ret_n_bind_mounts = n;
ae2a15bc 2452 *ret_empty_directories = TAKE_PTR(empty_directories);
6c47cd7d
LP
2453
2454 return (int) n;
2455
2456finish:
2457 bind_mount_free_many(bind_mounts, h);
2458 return r;
2459}
2460
6818c54c 2461static int apply_mount_namespace(
34cf6c43
YW
2462 const Unit *u,
2463 const ExecCommand *command,
6818c54c
LP
2464 const ExecContext *context,
2465 const ExecParameters *params,
7cc5ef5f
ZJS
2466 const ExecRuntime *runtime,
2467 char **error_path) {
6818c54c 2468
7bcef4ef 2469 _cleanup_strv_free_ char **empty_directories = NULL;
93c6bb51 2470 char *tmp = NULL, *var = NULL;
915e6d16 2471 const char *root_dir = NULL, *root_image = NULL;
228af36f 2472 NamespaceInfo ns_info;
165a31c0 2473 bool needs_sandboxing;
6c47cd7d 2474 BindMount *bind_mounts = NULL;
da6053d0 2475 size_t n_bind_mounts = 0;
6818c54c 2476 int r;
93c6bb51 2477
2b3c1b9e
DH
2478 assert(context);
2479
93c6bb51
DH
2480 /* The runtime struct only contains the parent of the private /tmp,
2481 * which is non-accessible to world users. Inside of it there's a /tmp
2482 * that is sticky, and that's the one we want to use here. */
2483
2484 if (context->private_tmp && runtime) {
2485 if (runtime->tmp_dir)
2486 tmp = strjoina(runtime->tmp_dir, "/tmp");
2487 if (runtime->var_tmp_dir)
2488 var = strjoina(runtime->var_tmp_dir, "/tmp");
2489 }
2490
915e6d16
LP
2491 if (params->flags & EXEC_APPLY_CHROOT) {
2492 root_image = context->root_image;
2493
2494 if (!root_image)
2495 root_dir = context->root_directory;
2496 }
93c6bb51 2497
6c47cd7d
LP
2498 r = compile_bind_mounts(context, params, &bind_mounts, &n_bind_mounts, &empty_directories);
2499 if (r < 0)
2500 return r;
2501
165a31c0 2502 needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & EXEC_COMMAND_FULLY_PRIVILEGED);
b5a33299
YW
2503 if (needs_sandboxing)
2504 ns_info = (NamespaceInfo) {
2505 .ignore_protect_paths = false,
2506 .private_dev = context->private_devices,
2507 .protect_control_groups = context->protect_control_groups,
2508 .protect_kernel_tunables = context->protect_kernel_tunables,
2509 .protect_kernel_modules = context->protect_kernel_modules,
aecd5ac6 2510 .protect_hostname = context->protect_hostname,
b5a33299 2511 .mount_apivfs = context->mount_apivfs,
228af36f 2512 .private_mounts = context->private_mounts,
b5a33299 2513 };
228af36f
LP
2514 else if (!context->dynamic_user && root_dir)
2515 /*
2516 * If DynamicUser=no and RootDirectory= is set then lets pass a relaxed
2517 * sandbox info, otherwise enforce it, don't ignore protected paths and
2518 * fail if we are enable to apply the sandbox inside the mount namespace.
2519 */
2520 ns_info = (NamespaceInfo) {
2521 .ignore_protect_paths = true,
2522 };
2523 else
2524 ns_info = (NamespaceInfo) {};
b5a33299 2525
37ed15d7
FB
2526 if (context->mount_flags == MS_SHARED)
2527 log_unit_debug(u, "shared mount propagation hidden by other fs namespacing unit settings: ignoring");
2528
915e6d16 2529 r = setup_namespace(root_dir, root_image,
7bcef4ef 2530 &ns_info, context->read_write_paths,
165a31c0
LP
2531 needs_sandboxing ? context->read_only_paths : NULL,
2532 needs_sandboxing ? context->inaccessible_paths : NULL,
6c47cd7d
LP
2533 empty_directories,
2534 bind_mounts,
2535 n_bind_mounts,
2abd4e38
YW
2536 context->temporary_filesystems,
2537 context->n_temporary_filesystems,
93c6bb51
DH
2538 tmp,
2539 var,
165a31c0
LP
2540 needs_sandboxing ? context->protect_home : PROTECT_HOME_NO,
2541 needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO,
915e6d16 2542 context->mount_flags,
7cc5ef5f
ZJS
2543 DISSECT_IMAGE_DISCARD_ON_LOOP,
2544 error_path);
93c6bb51 2545
6c47cd7d
LP
2546 bind_mount_free_many(bind_mounts, n_bind_mounts);
2547
1beab8b0 2548 /* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports
5238e957 2549 * that with a special, recognizable error ENOANO. In this case, silently proceed, but only if exclusively
1beab8b0
LP
2550 * sandboxing options were used, i.e. nothing such as RootDirectory= or BindMount= that would result in a
2551 * completely different execution environment. */
aca835ed
YW
2552 if (r == -ENOANO) {
2553 if (n_bind_mounts == 0 &&
2554 context->n_temporary_filesystems == 0 &&
2555 !root_dir && !root_image &&
2556 !context->dynamic_user) {
2557 log_unit_debug(u, "Failed to set up namespace, assuming containerized execution and ignoring.");
2558 return 0;
2559 }
2560
2194547e
LP
2561 log_unit_debug(u, "Failed to set up namespace, and refusing to continue since the selected namespacing options alter mount environment non-trivially.\n"
2562 "Bind mounts: %zu, temporary filesystems: %zu, root directory: %s, root image: %s, dynamic user: %s",
2563 n_bind_mounts, context->n_temporary_filesystems, yes_no(root_dir), yes_no(root_image), yes_no(context->dynamic_user));
2564
aca835ed 2565 return -EOPNOTSUPP;
93c6bb51
DH
2566 }
2567
2568 return r;
2569}
2570
915e6d16
LP
2571static int apply_working_directory(
2572 const ExecContext *context,
2573 const ExecParameters *params,
2574 const char *home,
376fecf6 2575 int *exit_status) {
915e6d16 2576
6732edab 2577 const char *d, *wd;
2b3c1b9e
DH
2578
2579 assert(context);
376fecf6 2580 assert(exit_status);
2b3c1b9e 2581
6732edab
LP
2582 if (context->working_directory_home) {
2583
376fecf6
LP
2584 if (!home) {
2585 *exit_status = EXIT_CHDIR;
6732edab 2586 return -ENXIO;
376fecf6 2587 }
6732edab 2588
2b3c1b9e 2589 wd = home;
6732edab
LP
2590
2591 } else if (context->working_directory)
2b3c1b9e
DH
2592 wd = context->working_directory;
2593 else
2594 wd = "/";
e7f1e7c6 2595
fa97f630 2596 if (params->flags & EXEC_APPLY_CHROOT)
2b3c1b9e 2597 d = wd;
fa97f630 2598 else
3b0e5bb5 2599 d = prefix_roota(context->root_directory, wd);
e7f1e7c6 2600
376fecf6
LP
2601 if (chdir(d) < 0 && !context->working_directory_missing_ok) {
2602 *exit_status = EXIT_CHDIR;
2b3c1b9e 2603 return -errno;
376fecf6 2604 }
e7f1e7c6
DH
2605
2606 return 0;
2607}
2608
fa97f630
JB
2609static int apply_root_directory(
2610 const ExecContext *context,
2611 const ExecParameters *params,
2612 const bool needs_mount_ns,
2613 int *exit_status) {
2614
2615 assert(context);
2616 assert(exit_status);
2617
2618 if (params->flags & EXEC_APPLY_CHROOT) {
2619 if (!needs_mount_ns && context->root_directory)
2620 if (chroot(context->root_directory) < 0) {
2621 *exit_status = EXIT_CHROOT;
2622 return -errno;
2623 }
2624 }
2625
2626 return 0;
2627}
2628
b1edf445 2629static int setup_keyring(
34cf6c43 2630 const Unit *u,
b1edf445
LP
2631 const ExecContext *context,
2632 const ExecParameters *p,
2633 uid_t uid, gid_t gid) {
2634
74dd6b51 2635 key_serial_t keyring;
e64c2d0b
DJL
2636 int r = 0;
2637 uid_t saved_uid;
2638 gid_t saved_gid;
74dd6b51
LP
2639
2640 assert(u);
b1edf445 2641 assert(context);
74dd6b51
LP
2642 assert(p);
2643
2644 /* Let's set up a new per-service "session" kernel keyring for each system service. This has the benefit that
2645 * each service runs with its own keyring shared among all processes of the service, but with no hook-up beyond
2646 * that scope, and in particular no link to the per-UID keyring. If we don't do this the keyring will be
2647 * automatically created on-demand and then linked to the per-UID keyring, by the kernel. The kernel's built-in
2648 * on-demand behaviour is very appropriate for login users, but probably not so much for system services, where
2649 * UIDs are not necessarily specific to a service but reused (at least in the case of UID 0). */
2650
b1edf445
LP
2651 if (context->keyring_mode == EXEC_KEYRING_INHERIT)
2652 return 0;
2653
e64c2d0b
DJL
2654 /* Acquiring a reference to the user keyring is nasty. We briefly change identity in order to get things set up
2655 * properly by the kernel. If we don't do that then we can't create it atomically, and that sucks for parallel
2656 * execution. This mimics what pam_keyinit does, too. Setting up session keyring, to be owned by the right user
2657 * & group is just as nasty as acquiring a reference to the user keyring. */
2658
2659 saved_uid = getuid();
2660 saved_gid = getgid();
2661
2662 if (gid_is_valid(gid) && gid != saved_gid) {
2663 if (setregid(gid, -1) < 0)
2664 return log_unit_error_errno(u, errno, "Failed to change GID for user keyring: %m");
2665 }
2666
2667 if (uid_is_valid(uid) && uid != saved_uid) {
2668 if (setreuid(uid, -1) < 0) {
2669 r = log_unit_error_errno(u, errno, "Failed to change UID for user keyring: %m");
2670 goto out;
2671 }
2672 }
2673
74dd6b51
LP
2674 keyring = keyctl(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
2675 if (keyring == -1) {
2676 if (errno == ENOSYS)
8002fb97 2677 log_unit_debug_errno(u, errno, "Kernel keyring not supported, ignoring.");
74dd6b51 2678 else if (IN_SET(errno, EACCES, EPERM))
8002fb97 2679 log_unit_debug_errno(u, errno, "Kernel keyring access prohibited, ignoring.");
74dd6b51 2680 else if (errno == EDQUOT)
8002fb97 2681 log_unit_debug_errno(u, errno, "Out of kernel keyrings to allocate, ignoring.");
74dd6b51 2682 else
e64c2d0b 2683 r = log_unit_error_errno(u, errno, "Setting up kernel keyring failed: %m");
74dd6b51 2684
e64c2d0b 2685 goto out;
74dd6b51
LP
2686 }
2687
e64c2d0b
DJL
2688 /* When requested link the user keyring into the session keyring. */
2689 if (context->keyring_mode == EXEC_KEYRING_SHARED) {
2690
2691 if (keyctl(KEYCTL_LINK,
2692 KEY_SPEC_USER_KEYRING,
2693 KEY_SPEC_SESSION_KEYRING, 0, 0) < 0) {
2694 r = log_unit_error_errno(u, errno, "Failed to link user keyring into session keyring: %m");
2695 goto out;
2696 }
2697 }
2698
2699 /* Restore uid/gid back */
2700 if (uid_is_valid(uid) && uid != saved_uid) {
2701 if (setreuid(saved_uid, -1) < 0) {
2702 r = log_unit_error_errno(u, errno, "Failed to change UID back for user keyring: %m");
2703 goto out;
2704 }
2705 }
2706
2707 if (gid_is_valid(gid) && gid != saved_gid) {
2708 if (setregid(saved_gid, -1) < 0)
2709 return log_unit_error_errno(u, errno, "Failed to change GID back for user keyring: %m");
2710 }
2711
2712 /* Populate they keyring with the invocation ID by default, as original saved_uid. */
b3415f5d
LP
2713 if (!sd_id128_is_null(u->invocation_id)) {
2714 key_serial_t key;
2715
2716 key = add_key("user", "invocation_id", &u->invocation_id, sizeof(u->invocation_id), KEY_SPEC_SESSION_KEYRING);
2717 if (key == -1)
8002fb97 2718 log_unit_debug_errno(u, errno, "Failed to add invocation ID to keyring, ignoring: %m");
b3415f5d
LP
2719 else {
2720 if (keyctl(KEYCTL_SETPERM, key,
2721 KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH|
2722 KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH, 0, 0) < 0)
e64c2d0b 2723 r = log_unit_error_errno(u, errno, "Failed to restrict invocation ID permission: %m");
b3415f5d
LP
2724 }
2725 }
2726
e64c2d0b
DJL
2727out:
2728 /* Revert back uid & gid for the the last time, and exit */
2729 /* no extra logging, as only the first already reported error matters */
2730 if (getuid() != saved_uid)
2731 (void) setreuid(saved_uid, -1);
b1edf445 2732
e64c2d0b
DJL
2733 if (getgid() != saved_gid)
2734 (void) setregid(saved_gid, -1);
b1edf445 2735
e64c2d0b 2736 return r;
74dd6b51
LP
2737}
2738
3042bbeb 2739static void append_socket_pair(int *array, size_t *n, const int pair[static 2]) {
29206d46
LP
2740 assert(array);
2741 assert(n);
2caa38e9 2742 assert(pair);
29206d46
LP
2743
2744 if (pair[0] >= 0)
2745 array[(*n)++] = pair[0];
2746 if (pair[1] >= 0)
2747 array[(*n)++] = pair[1];
2748}
2749
a34ceba6
LP
2750static int close_remaining_fds(
2751 const ExecParameters *params,
34cf6c43
YW
2752 const ExecRuntime *runtime,
2753 const DynamicCreds *dcreds,
00d9ef85 2754 int user_lookup_fd,
a34ceba6 2755 int socket_fd,
5686391b 2756 int exec_fd,
da6053d0 2757 int *fds, size_t n_fds) {
a34ceba6 2758
da6053d0 2759 size_t n_dont_close = 0;
00d9ef85 2760 int dont_close[n_fds + 12];
a34ceba6
LP
2761
2762 assert(params);
2763
2764 if (params->stdin_fd >= 0)
2765 dont_close[n_dont_close++] = params->stdin_fd;
2766 if (params->stdout_fd >= 0)
2767 dont_close[n_dont_close++] = params->stdout_fd;
2768 if (params->stderr_fd >= 0)
2769 dont_close[n_dont_close++] = params->stderr_fd;
2770
2771 if (socket_fd >= 0)
2772 dont_close[n_dont_close++] = socket_fd;
5686391b
LP
2773 if (exec_fd >= 0)
2774 dont_close[n_dont_close++] = exec_fd;
a34ceba6
LP
2775 if (n_fds > 0) {
2776 memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
2777 n_dont_close += n_fds;
2778 }
2779
29206d46
LP
2780 if (runtime)
2781 append_socket_pair(dont_close, &n_dont_close, runtime->netns_storage_socket);
2782
2783 if (dcreds) {
2784 if (dcreds->user)
2785 append_socket_pair(dont_close, &n_dont_close, dcreds->user->storage_socket);
2786 if (dcreds->group)
2787 append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket);
a34ceba6
LP
2788 }
2789
00d9ef85
LP
2790 if (user_lookup_fd >= 0)
2791 dont_close[n_dont_close++] = user_lookup_fd;
2792
a34ceba6
LP
2793 return close_all_fds(dont_close, n_dont_close);
2794}
2795
00d9ef85
LP
2796static int send_user_lookup(
2797 Unit *unit,
2798 int user_lookup_fd,
2799 uid_t uid,
2800 gid_t gid) {
2801
2802 assert(unit);
2803
2804 /* Send the resolved UID/GID to PID 1 after we learnt it. We send a single datagram, containing the UID/GID
2805 * data as well as the unit name. Note that we suppress sending this if no user/group to resolve was
2806 * specified. */
2807
2808 if (user_lookup_fd < 0)
2809 return 0;
2810
2811 if (!uid_is_valid(uid) && !gid_is_valid(gid))
2812 return 0;
2813
2814 if (writev(user_lookup_fd,
2815 (struct iovec[]) {
e6a7ec4b
LP
2816 IOVEC_INIT(&uid, sizeof(uid)),
2817 IOVEC_INIT(&gid, sizeof(gid)),
2818 IOVEC_INIT_STRING(unit->id) }, 3) < 0)
00d9ef85
LP
2819 return -errno;
2820
2821 return 0;
2822}
2823
6732edab
LP
2824static int acquire_home(const ExecContext *c, uid_t uid, const char** home, char **buf) {
2825 int r;
2826
2827 assert(c);
2828 assert(home);
2829 assert(buf);
2830
2831 /* If WorkingDirectory=~ is set, try to acquire a usable home directory. */
2832
2833 if (*home)
2834 return 0;
2835
2836 if (!c->working_directory_home)
2837 return 0;
2838
6732edab
LP
2839 r = get_home_dir(buf);
2840 if (r < 0)
2841 return r;
2842
2843 *home = *buf;
2844 return 1;
2845}
2846
da50b85a
LP
2847static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p, char ***ret) {
2848 _cleanup_strv_free_ char ** list = NULL;
2849 ExecDirectoryType t;
2850 int r;
2851
2852 assert(c);
2853 assert(p);
2854 assert(ret);
2855
2856 assert(c->dynamic_user);
2857
2858 /* Compile a list of paths that it might make sense to read the owning UID from to use as initial candidate for
2859 * dynamic UID allocation, in order to save us from doing costly recursive chown()s of the special
2860 * directories. */
2861
2862 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
2863 char **i;
2864
2865 if (t == EXEC_DIRECTORY_CONFIGURATION)
2866 continue;
2867
2868 if (!p->prefix[t])
2869 continue;
2870
2871 STRV_FOREACH(i, c->directories[t].paths) {
2872 char *e;
2873
494d0247 2874 if (exec_directory_is_private(c, t))
657ee2d8 2875 e = path_join(p->prefix[t], "private", *i);
494d0247
YW
2876 else
2877 e = path_join(p->prefix[t], *i);
da50b85a
LP
2878 if (!e)
2879 return -ENOMEM;
2880
2881 r = strv_consume(&list, e);
2882 if (r < 0)
2883 return r;
2884 }
2885 }
2886
ae2a15bc 2887 *ret = TAKE_PTR(list);
da50b85a
LP
2888
2889 return 0;
2890}
2891
34cf6c43
YW
2892static char *exec_command_line(char **argv);
2893
78f93209
LP
2894static int exec_parameters_get_cgroup_path(const ExecParameters *params, char **ret) {
2895 bool using_subcgroup;
2896 char *p;
2897
2898 assert(params);
2899 assert(ret);
2900
2901 if (!params->cgroup_path)
2902 return -EINVAL;
2903
2904 /* If we are called for a unit where cgroup delegation is on, and the payload created its own populated
2905 * subcgroup (which we expect it to do, after all it asked for delegation), then we cannot place the control
2906 * processes started after the main unit's process in the unit's main cgroup because it is now an inner one,
2907 * and inner cgroups may not contain processes. Hence, if delegation is on, and this is a control process,
2908 * let's use ".control" as subcgroup instead. Note that we do so only for ExecStartPost=, ExecReload=,
2909 * ExecStop=, ExecStopPost=, i.e. for the commands where the main process is already forked. For ExecStartPre=
2910 * this is not necessary, the cgroup is still empty. We distinguish these cases with the EXEC_CONTROL_CGROUP
2911 * flag, which is only passed for the former statements, not for the latter. */
2912
2913 using_subcgroup = FLAGS_SET(params->flags, EXEC_CONTROL_CGROUP|EXEC_CGROUP_DELEGATE|EXEC_IS_CONTROL);
2914 if (using_subcgroup)
657ee2d8 2915 p = path_join(params->cgroup_path, ".control");
78f93209
LP
2916 else
2917 p = strdup(params->cgroup_path);
2918 if (!p)
2919 return -ENOMEM;
2920
2921 *ret = p;
2922 return using_subcgroup;
2923}
2924
ff0af2a1 2925static int exec_child(
f2341e0a 2926 Unit *unit,
34cf6c43 2927 const ExecCommand *command,
ff0af2a1
LP
2928 const ExecContext *context,
2929 const ExecParameters *params,
2930 ExecRuntime *runtime,
29206d46 2931 DynamicCreds *dcreds,
ff0af2a1 2932 int socket_fd,
2caa38e9 2933 const int named_iofds[static 3],
4c47affc 2934 int *fds,
da6053d0 2935 size_t n_socket_fds,
25b583d7 2936 size_t n_storage_fds,
ff0af2a1 2937 char **files_env,
00d9ef85 2938 int user_lookup_fd,
12145637 2939 int *exit_status) {
d35fbf6b 2940
7ca69792 2941 _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **replaced_argv = NULL;
5686391b 2942 int *fds_with_exec_fd, n_fds_with_exec_fd, r, ngids = 0, exec_fd = -1;
4d885bd3
DH
2943 _cleanup_free_ gid_t *supplementary_gids = NULL;
2944 const char *username = NULL, *groupname = NULL;
5686391b 2945 _cleanup_free_ char *home_buffer = NULL;
2b3c1b9e 2946 const char *home = NULL, *shell = NULL;
7ca69792 2947 char **final_argv = NULL;
7bce046b
LP
2948 dev_t journal_stream_dev = 0;
2949 ino_t journal_stream_ino = 0;
165a31c0
LP
2950 bool needs_sandboxing, /* Do we need to set up full sandboxing? (i.e. all namespacing, all MAC stuff, caps, yadda yadda */
2951 needs_setuid, /* Do we need to do the actual setresuid()/setresgid() calls? */
2952 needs_mount_namespace, /* Do we need to set up a mount namespace for this kernel? */
2953 needs_ambient_hack; /* Do we need to apply the ambient capabilities hack? */
349cc4a5 2954#if HAVE_SELINUX
7f59dd35 2955 _cleanup_free_ char *mac_selinux_context_net = NULL;
43b1f709 2956 bool use_selinux = false;
ecfbc84f 2957#endif
f9fa32f0 2958#if ENABLE_SMACK
43b1f709 2959 bool use_smack = false;
ecfbc84f 2960#endif
349cc4a5 2961#if HAVE_APPARMOR
43b1f709 2962 bool use_apparmor = false;
ecfbc84f 2963#endif
fed1e721
LP
2964 uid_t uid = UID_INVALID;
2965 gid_t gid = GID_INVALID;
da6053d0 2966 size_t n_fds;
3536f49e 2967 ExecDirectoryType dt;
165a31c0 2968 int secure_bits;
034c6ed7 2969
f2341e0a 2970 assert(unit);
5cb5a6ff
LP
2971 assert(command);
2972 assert(context);
d35fbf6b 2973 assert(params);
ff0af2a1 2974 assert(exit_status);
d35fbf6b
DM
2975
2976 rename_process_from_path(command->path);
2977
2978 /* We reset exactly these signals, since they are the
2979 * only ones we set to SIG_IGN in the main daemon. All
2980 * others we leave untouched because we set them to
2981 * SIG_DFL or a valid handler initially, both of which
2982 * will be demoted to SIG_DFL. */
ce30c8dc
LP
2983 (void) default_signals(SIGNALS_CRASH_HANDLER,
2984 SIGNALS_IGNORE, -1);
d35fbf6b
DM
2985
2986 if (context->ignore_sigpipe)
ce30c8dc 2987 (void) ignore_signals(SIGPIPE, -1);
d35fbf6b 2988
ff0af2a1
LP
2989 r = reset_signal_mask();
2990 if (r < 0) {
2991 *exit_status = EXIT_SIGNAL_MASK;
12145637 2992 return log_unit_error_errno(unit, r, "Failed to set process signal mask: %m");
d35fbf6b 2993 }
034c6ed7 2994
d35fbf6b
DM
2995 if (params->idle_pipe)
2996 do_idle_pipe_dance(params->idle_pipe);
4f2d528d 2997
2c027c62
LP
2998 /* Close fds we don't need very early to make sure we don't block init reexecution because it cannot bind its
2999 * sockets. Among the fds we close are the logging fds, and we want to keep them closed, so that we don't have
3000 * any fds open we don't really want open during the transition. In order to make logging work, we switch the
3001 * log subsystem into open_when_needed mode, so that it reopens the logs on every single log call. */
ff0af2a1 3002
d35fbf6b 3003 log_forget_fds();
2c027c62 3004 log_set_open_when_needed(true);
4f2d528d 3005
40a80078
LP
3006 /* In case anything used libc syslog(), close this here, too */
3007 closelog();
3008
5686391b
LP
3009 n_fds = n_socket_fds + n_storage_fds;
3010 r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, params->exec_fd, fds, n_fds);
ff0af2a1
LP
3011 if (r < 0) {
3012 *exit_status = EXIT_FDS;
12145637 3013 return log_unit_error_errno(unit, r, "Failed to close unwanted file descriptors: %m");
8c7be95e
LP
3014 }
3015
d35fbf6b
DM
3016 if (!context->same_pgrp)
3017 if (setsid() < 0) {
ff0af2a1 3018 *exit_status = EXIT_SETSID;
12145637 3019 return log_unit_error_errno(unit, errno, "Failed to create new process session: %m");
d35fbf6b 3020 }
9e2f7c11 3021
1e22b5cd 3022 exec_context_tty_reset(context, params);
d35fbf6b 3023
c891efaf 3024 if (unit_shall_confirm_spawn(unit)) {
7d5ceb64 3025 const char *vc = params->confirm_spawn;
3b20f877
FB
3026 _cleanup_free_ char *cmdline = NULL;
3027
ee39ca20 3028 cmdline = exec_command_line(command->argv);
3b20f877 3029 if (!cmdline) {
0460aa5c 3030 *exit_status = EXIT_MEMORY;
12145637 3031 return log_oom();
3b20f877 3032 }
d35fbf6b 3033
eedf223a 3034 r = ask_for_confirmation(vc, unit, cmdline);
3b20f877
FB
3035 if (r != CONFIRM_EXECUTE) {
3036 if (r == CONFIRM_PRETEND_SUCCESS) {
3037 *exit_status = EXIT_SUCCESS;
3038 return 0;
3039 }
ff0af2a1 3040 *exit_status = EXIT_CONFIRM;
12145637 3041 log_unit_error(unit, "Execution cancelled by the user");
d35fbf6b 3042 return -ECANCELED;
d35fbf6b
DM
3043 }
3044 }
1a63a750 3045
d521916d
LP
3046 /* We are about to invoke NSS and PAM modules. Let's tell them what we are doing here, maybe they care. This is
3047 * used by nss-resolve to disable itself when we are about to start systemd-resolved, to avoid deadlocks. Note
3048 * that these env vars do not survive the execve(), which means they really only apply to the PAM and NSS
3049 * invocations themselves. Also note that while we'll only invoke NSS modules involved in user management they
3050 * might internally call into other NSS modules that are involved in hostname resolution, we never know. */
3051 if (setenv("SYSTEMD_ACTIVATION_UNIT", unit->id, true) != 0 ||
3052 setenv("SYSTEMD_ACTIVATION_SCOPE", MANAGER_IS_SYSTEM(unit->manager) ? "system" : "user", true) != 0) {
3053 *exit_status = EXIT_MEMORY;
3054 return log_unit_error_errno(unit, errno, "Failed to update environment: %m");
3055 }
3056
29206d46 3057 if (context->dynamic_user && dcreds) {
da50b85a 3058 _cleanup_strv_free_ char **suggested_paths = NULL;
29206d46 3059
d521916d
LP
3060 /* On top of that, make sure we bypass our own NSS module nss-systemd comprehensively for any NSS
3061 * checks, if DynamicUser=1 is used, as we shouldn't create a feedback loop with ourselves here.*/
409093fe
LP
3062 if (putenv((char*) "SYSTEMD_NSS_DYNAMIC_BYPASS=1") != 0) {
3063 *exit_status = EXIT_USER;
12145637 3064 return log_unit_error_errno(unit, errno, "Failed to update environment: %m");
409093fe
LP
3065 }
3066
da50b85a
LP
3067 r = compile_suggested_paths(context, params, &suggested_paths);
3068 if (r < 0) {
3069 *exit_status = EXIT_MEMORY;
3070 return log_oom();
3071 }
3072
3073 r = dynamic_creds_realize(dcreds, suggested_paths, &uid, &gid);
ff0af2a1
LP
3074 if (r < 0) {
3075 *exit_status = EXIT_USER;
e2b0cc34
YW
3076 if (r == -EILSEQ) {
3077 log_unit_error(unit, "Failed to update dynamic user credentials: User or group with specified name already exists.");
3078 return -EOPNOTSUPP;
3079 }
12145637 3080 return log_unit_error_errno(unit, r, "Failed to update dynamic user credentials: %m");
524daa8c 3081 }
524daa8c 3082
70dd455c 3083 if (!uid_is_valid(uid)) {
29206d46 3084 *exit_status = EXIT_USER;
12145637 3085 log_unit_error(unit, "UID validation failed for \""UID_FMT"\"", uid);
70dd455c
ZJS
3086 return -ESRCH;
3087 }
3088
3089 if (!gid_is_valid(gid)) {
3090 *exit_status = EXIT_USER;
12145637 3091 log_unit_error(unit, "GID validation failed for \""GID_FMT"\"", gid);
29206d46
LP
3092 return -ESRCH;
3093 }
5bc7452b 3094
29206d46
LP
3095 if (dcreds->user)
3096 username = dcreds->user->name;
3097
3098 } else {
4d885bd3
DH
3099 r = get_fixed_user(context, &username, &uid, &gid, &home, &shell);
3100 if (r < 0) {
3101 *exit_status = EXIT_USER;
12145637 3102 return log_unit_error_errno(unit, r, "Failed to determine user credentials: %m");
5bc7452b 3103 }
5bc7452b 3104
4d885bd3
DH
3105 r = get_fixed_group(context, &groupname, &gid);
3106 if (r < 0) {
3107 *exit_status = EXIT_GROUP;
12145637 3108 return log_unit_error_errno(unit, r, "Failed to determine group credentials: %m");
4d885bd3 3109 }
cdc5d5c5 3110 }
29206d46 3111
cdc5d5c5
DH
3112 /* Initialize user supplementary groups and get SupplementaryGroups= ones */
3113 r = get_supplementary_groups(context, username, groupname, gid,
3114 &supplementary_gids, &ngids);
3115 if (r < 0) {
3116 *exit_status = EXIT_GROUP;
12145637 3117 return log_unit_error_errno(unit, r, "Failed to determine supplementary groups: %m");
29206d46 3118 }
5bc7452b 3119
00d9ef85
LP
3120 r = send_user_lookup(unit, user_lookup_fd, uid, gid);
3121 if (r < 0) {
3122 *exit_status = EXIT_USER;
12145637 3123 return log_unit_error_errno(unit, r, "Failed to send user credentials to PID1: %m");
00d9ef85
LP
3124 }
3125
3126 user_lookup_fd = safe_close(user_lookup_fd);
3127
6732edab
LP
3128 r = acquire_home(context, uid, &home, &home_buffer);
3129 if (r < 0) {
3130 *exit_status = EXIT_CHDIR;
12145637 3131 return log_unit_error_errno(unit, r, "Failed to determine $HOME for user: %m");
6732edab
LP
3132 }
3133
d35fbf6b
DM
3134 /* If a socket is connected to STDIN/STDOUT/STDERR, we
3135 * must sure to drop O_NONBLOCK */
3136 if (socket_fd >= 0)
a34ceba6 3137 (void) fd_nonblock(socket_fd, false);
acbb0225 3138
4c70a4a7
MS
3139 /* Journald will try to look-up our cgroup in order to populate _SYSTEMD_CGROUP and _SYSTEMD_UNIT fields.
3140 * Hence we need to migrate to the target cgroup from init.scope before connecting to journald */
3141 if (params->cgroup_path) {
3142 _cleanup_free_ char *p = NULL;
3143
3144 r = exec_parameters_get_cgroup_path(params, &p);
3145 if (r < 0) {
3146 *exit_status = EXIT_CGROUP;
3147 return log_unit_error_errno(unit, r, "Failed to acquire cgroup path: %m");
3148 }
3149
3150 r = cg_attach_everywhere(params->cgroup_supported, p, 0, NULL, NULL);
3151 if (r < 0) {
3152 *exit_status = EXIT_CGROUP;
3153 return log_unit_error_errno(unit, r, "Failed to attach to cgroup %s: %m", p);
3154 }
3155 }
3156
a8d08f39
LP
3157 if (context->network_namespace_path && runtime && runtime->netns_storage_socket[0] >= 0) {
3158 r = open_netns_path(runtime->netns_storage_socket, context->network_namespace_path);
3159 if (r < 0) {
3160 *exit_status = EXIT_NETWORK;
3161 return log_unit_error_errno(unit, r, "Failed to open network namespace path %s: %m", context->network_namespace_path);
3162 }
3163 }
3164
52c239d7 3165 r = setup_input(context, params, socket_fd, named_iofds);
ff0af2a1
LP
3166 if (r < 0) {
3167 *exit_status = EXIT_STDIN;
12145637 3168 return log_unit_error_errno(unit, r, "Failed to set up standard input: %m");
d35fbf6b 3169 }
034c6ed7 3170
52c239d7 3171 r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
ff0af2a1
LP
3172 if (r < 0) {
3173 *exit_status = EXIT_STDOUT;
12145637 3174 return log_unit_error_errno(unit, r, "Failed to set up standard output: %m");
d35fbf6b
DM
3175 }
3176
52c239d7 3177 r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
ff0af2a1
LP
3178 if (r < 0) {
3179 *exit_status = EXIT_STDERR;
12145637 3180 return log_unit_error_errno(unit, r, "Failed to set up standard error output: %m");
d35fbf6b
DM
3181 }
3182
d35fbf6b 3183 if (context->oom_score_adjust_set) {
9f8168eb
LP
3184 /* When we can't make this change due to EPERM, then let's silently skip over it. User namespaces
3185 * prohibit write access to this file, and we shouldn't trip up over that. */
3186 r = set_oom_score_adjust(context->oom_score_adjust);
12145637 3187 if (IN_SET(r, -EPERM, -EACCES))
f2341e0a 3188 log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
12145637 3189 else if (r < 0) {
ff0af2a1 3190 *exit_status = EXIT_OOM_ADJUST;
12145637 3191 return log_unit_error_errno(unit, r, "Failed to adjust OOM setting: %m");
613b411c 3192 }
d35fbf6b
DM
3193 }
3194
3195 if (context->nice_set)
3196 if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
ff0af2a1 3197 *exit_status = EXIT_NICE;
12145637 3198 return log_unit_error_errno(unit, errno, "Failed to set up process scheduling priority (nice level): %m");
613b411c
LP
3199 }
3200
d35fbf6b
DM
3201 if (context->cpu_sched_set) {
3202 struct sched_param param = {
3203 .sched_priority = context->cpu_sched_priority,
3204 };
3205
ff0af2a1
LP
3206 r = sched_setscheduler(0,
3207 context->cpu_sched_policy |
3208 (context->cpu_sched_reset_on_fork ?
3209 SCHED_RESET_ON_FORK : 0),
3210 &param);
3211 if (r < 0) {
3212 *exit_status = EXIT_SETSCHEDULER;
12145637 3213 return log_unit_error_errno(unit, errno, "Failed to set up CPU scheduling: %m");
fc9b2a84 3214 }
d35fbf6b 3215 }
fc9b2a84 3216
0985c7c4
ZJS
3217 if (context->cpu_set.set)
3218 if (sched_setaffinity(0, context->cpu_set.allocated, context->cpu_set.set) < 0) {
ff0af2a1 3219 *exit_status = EXIT_CPUAFFINITY;
12145637 3220 return log_unit_error_errno(unit, errno, "Failed to set up CPU affinity: %m");
034c6ed7
LP
3221 }
3222
b070c7c0
MS
3223 if (mpol_is_valid(numa_policy_get_type(&context->numa_policy))) {
3224 r = apply_numa_policy(&context->numa_policy);
3225 if (r == -EOPNOTSUPP)
33fe9e3f 3226 log_unit_debug_errno(unit, r, "NUMA support not available, ignoring.");
b070c7c0
MS
3227 else if (r < 0) {
3228 *exit_status = EXIT_NUMA_POLICY;
3229 return log_unit_error_errno(unit, r, "Failed to set NUMA memory policy: %m");
3230 }
3231 }
3232
d35fbf6b
DM
3233 if (context->ioprio_set)
3234 if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
ff0af2a1 3235 *exit_status = EXIT_IOPRIO;
12145637 3236 return log_unit_error_errno(unit, errno, "Failed to set up IO scheduling priority: %m");
d35fbf6b 3237 }
da726a4d 3238
d35fbf6b
DM
3239 if (context->timer_slack_nsec != NSEC_INFINITY)
3240 if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
ff0af2a1 3241 *exit_status = EXIT_TIMERSLACK;
12145637 3242 return log_unit_error_errno(unit, errno, "Failed to set up timer slack: %m");
4c2630eb 3243 }
9eba9da4 3244
21022b9d
LP
3245 if (context->personality != PERSONALITY_INVALID) {
3246 r = safe_personality(context->personality);
3247 if (r < 0) {
ff0af2a1 3248 *exit_status = EXIT_PERSONALITY;
12145637 3249 return log_unit_error_errno(unit, r, "Failed to set up execution domain (personality): %m");
4c2630eb 3250 }
21022b9d 3251 }
94f04347 3252
d35fbf6b 3253 if (context->utmp_id)
df0ff127 3254 utmp_put_init_process(context->utmp_id, getpid_cached(), getsid(0),
6a93917d 3255 context->tty_path,
023a4f67
LP
3256 context->utmp_mode == EXEC_UTMP_INIT ? INIT_PROCESS :
3257 context->utmp_mode == EXEC_UTMP_LOGIN ? LOGIN_PROCESS :
3258 USER_PROCESS,
6a93917d 3259 username);
d35fbf6b 3260
08f67696 3261 if (uid_is_valid(uid)) {
ff0af2a1
LP
3262 r = chown_terminal(STDIN_FILENO, uid);
3263 if (r < 0) {
3264 *exit_status = EXIT_STDIN;
12145637 3265 return log_unit_error_errno(unit, r, "Failed to change ownership of terminal: %m");
071830ff 3266 }
d35fbf6b 3267 }
8e274523 3268
4e1dfa45 3269 /* If delegation is enabled we'll pass ownership of the cgroup to the user of the new process. On cgroup v1
62b9bb26 3270 * this is only about systemd's own hierarchy, i.e. not the controller hierarchies, simply because that's not
4e1dfa45 3271 * safe. On cgroup v2 there's only one hierarchy anyway, and delegation is safe there, hence in that case only
62b9bb26 3272 * touch a single hierarchy too. */
584b8688 3273 if (params->cgroup_path && context->user && (params->flags & EXEC_CGROUP_DELEGATE)) {
62b9bb26 3274 r = cg_set_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, uid, gid);
ff0af2a1
LP
3275 if (r < 0) {
3276 *exit_status = EXIT_CGROUP;
12145637 3277 return log_unit_error_errno(unit, r, "Failed to adjust control group access: %m");
034c6ed7 3278 }
d35fbf6b 3279 }
034c6ed7 3280
72fd1768 3281 for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) {
8679efde 3282 r = setup_exec_directory(context, params, uid, gid, dt, exit_status);
12145637
LP
3283 if (r < 0)
3284 return log_unit_error_errno(unit, r, "Failed to set up special execution directory in %s: %m", params->prefix[dt]);
d35fbf6b 3285 }
94f04347 3286
7bce046b 3287 r = build_environment(
fd63e712 3288 unit,
7bce046b
LP
3289 context,
3290 params,
3291 n_fds,
3292 home,
3293 username,
3294 shell,
3295 journal_stream_dev,
3296 journal_stream_ino,
3297 &our_env);
2065ca69
JW
3298 if (r < 0) {
3299 *exit_status = EXIT_MEMORY;
12145637 3300 return log_oom();
2065ca69
JW
3301 }
3302
3303 r = build_pass_environment(context, &pass_env);
3304 if (r < 0) {
3305 *exit_status = EXIT_MEMORY;
12145637 3306 return log_oom();
2065ca69
JW
3307 }
3308
3309 accum_env = strv_env_merge(5,
3310 params->environment,
3311 our_env,
3312 pass_env,
3313 context->environment,
3314 files_env,
3315 NULL);
3316 if (!accum_env) {
3317 *exit_status = EXIT_MEMORY;
12145637 3318 return log_oom();
2065ca69 3319 }
1280503b 3320 accum_env = strv_env_clean(accum_env);
2065ca69 3321
096424d1 3322 (void) umask(context->umask);
b213e1c1 3323
b1edf445 3324 r = setup_keyring(unit, context, params, uid, gid);
74dd6b51
LP
3325 if (r < 0) {
3326 *exit_status = EXIT_KEYRING;
12145637 3327 return log_unit_error_errno(unit, r, "Failed to set up kernel keyring: %m");
74dd6b51
LP
3328 }
3329
165a31c0 3330 /* We need sandboxing if the caller asked us to apply it and the command isn't explicitly excepted from it */
1703fa41 3331 needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & EXEC_COMMAND_FULLY_PRIVILEGED);
7f18ef0a 3332
165a31c0
LP
3333 /* We need the ambient capability hack, if the caller asked us to apply it and the command is marked for it, and the kernel doesn't actually support ambient caps */
3334 needs_ambient_hack = (params->flags & EXEC_APPLY_SANDBOXING) && (command->flags & EXEC_COMMAND_AMBIENT_MAGIC) && !ambient_capabilities_supported();
7f18ef0a 3335
165a31c0
LP
3336 /* We need setresuid() if the caller asked us to apply sandboxing and the command isn't explicitly excepted from either whole sandboxing or just setresuid() itself, and the ambient hack is not desired */
3337 if (needs_ambient_hack)
3338 needs_setuid = false;
3339 else
3340 needs_setuid = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID));
3341
3342 if (needs_sandboxing) {
7f18ef0a
FK
3343 /* MAC enablement checks need to be done before a new mount ns is created, as they rely on /sys being
3344 * present. The actual MAC context application will happen later, as late as possible, to avoid
3345 * impacting our own code paths. */
3346
349cc4a5 3347#if HAVE_SELINUX
43b1f709 3348 use_selinux = mac_selinux_use();
7f18ef0a 3349#endif
f9fa32f0 3350#if ENABLE_SMACK
43b1f709 3351 use_smack = mac_smack_use();
7f18ef0a 3352#endif
349cc4a5 3353#if HAVE_APPARMOR
43b1f709 3354 use_apparmor = mac_apparmor_use();
7f18ef0a 3355#endif
165a31c0 3356 }
7f18ef0a 3357
ce932d2d
LP
3358 if (needs_sandboxing) {
3359 int which_failed;
3360
3361 /* Let's set the resource limits before we call into PAM, so that pam_limits wins over what
3362 * is set here. (See below.) */
3363
3364 r = setrlimit_closest_all((const struct rlimit* const *) context->rlimit, &which_failed);
3365 if (r < 0) {
3366 *exit_status = EXIT_LIMITS;
3367 return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed));
3368 }
3369 }
3370
165a31c0 3371 if (needs_setuid) {
ce932d2d
LP
3372
3373 /* Let's call into PAM after we set up our own idea of resource limits to that pam_limits
3374 * wins here. (See above.) */
3375
165a31c0
LP
3376 if (context->pam_name && username) {
3377 r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds);
3378 if (r < 0) {
3379 *exit_status = EXIT_PAM;
12145637 3380 return log_unit_error_errno(unit, r, "Failed to set up PAM session: %m");
165a31c0
LP
3381 }
3382 }
b213e1c1 3383 }
ac45f971 3384
a8d08f39
LP
3385 if ((context->private_network || context->network_namespace_path) && runtime && runtime->netns_storage_socket[0] >= 0) {
3386
6e2d7c4f
MS
3387 if (ns_type_supported(NAMESPACE_NET)) {
3388 r = setup_netns(runtime->netns_storage_socket);
3389 if (r < 0) {
3390 *exit_status = EXIT_NETWORK;
3391 return log_unit_error_errno(unit, r, "Failed to set up network namespacing: %m");
3392 }
a8d08f39
LP
3393 } else if (context->network_namespace_path) {
3394 *exit_status = EXIT_NETWORK;
3395 return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EOPNOTSUPP), "NetworkNamespacePath= is not supported, refusing.");
6e2d7c4f
MS
3396 } else
3397 log_unit_warning(unit, "PrivateNetwork=yes is configured, but the kernel does not support network namespaces, ignoring.");
d35fbf6b 3398 }
169c1bda 3399
ee818b89 3400 needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime);
ee818b89 3401 if (needs_mount_namespace) {
7cc5ef5f
ZJS
3402 _cleanup_free_ char *error_path = NULL;
3403
3404 r = apply_mount_namespace(unit, command, context, params, runtime, &error_path);
3fbe8dbe
LP
3405 if (r < 0) {
3406 *exit_status = EXIT_NAMESPACE;
7cc5ef5f
ZJS
3407 return log_unit_error_errno(unit, r, "Failed to set up mount namespacing%s%s: %m",
3408 error_path ? ": " : "", strempty(error_path));
3fbe8dbe 3409 }
d35fbf6b 3410 }
81a2b7ce 3411
aecd5ac6
TM
3412 if (context->protect_hostname) {
3413 if (ns_type_supported(NAMESPACE_UTS)) {
3414 if (unshare(CLONE_NEWUTS) < 0) {
3415 *exit_status = EXIT_NAMESPACE;
3416 return log_unit_error_errno(unit, errno, "Failed to set up UTS namespacing: %m");
3417 }
3418 } else
3419 log_unit_warning(unit, "ProtectHostname=yes is configured, but the kernel does not support UTS namespaces, ignoring namespace setup.");
3420#if HAVE_SECCOMP
3421 r = seccomp_protect_hostname();
3422 if (r < 0) {
3423 *exit_status = EXIT_SECCOMP;
3424 return log_unit_error_errno(unit, r, "Failed to apply hostname restrictions: %m");
3425 }
3426#endif
3427 }
3428
bbeea271 3429 /* Drop groups as early as possbile */
165a31c0 3430 if (needs_setuid) {
709dbeac 3431 r = enforce_groups(gid, supplementary_gids, ngids);
096424d1
LP
3432 if (r < 0) {
3433 *exit_status = EXIT_GROUP;
12145637 3434 return log_unit_error_errno(unit, r, "Changing group credentials failed: %m");
096424d1 3435 }
165a31c0 3436 }
096424d1 3437
165a31c0 3438 if (needs_sandboxing) {
349cc4a5 3439#if HAVE_SELINUX
43b1f709 3440 if (use_selinux && params->selinux_context_net && socket_fd >= 0) {
937ccce9
LP
3441 r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net);
3442 if (r < 0) {
3443 *exit_status = EXIT_SELINUX_CONTEXT;
12145637 3444 return log_unit_error_errno(unit, r, "Failed to determine SELinux context: %m");
937ccce9 3445 }
9008e1ac 3446 }
9008e1ac
MS
3447#endif
3448
937ccce9
LP
3449 if (context->private_users) {
3450 r = setup_private_users(uid, gid);
3451 if (r < 0) {
3452 *exit_status = EXIT_USER;
12145637 3453 return log_unit_error_errno(unit, r, "Failed to set up user namespacing: %m");
937ccce9 3454 }
d251207d
LP
3455 }
3456 }
3457
165a31c0 3458 /* We repeat the fd closing here, to make sure that nothing is leaked from the PAM modules. Note that we are
5686391b
LP
3459 * more aggressive this time since socket_fd and the netns fds we don't need anymore. We do keep the exec_fd
3460 * however if we have it as we want to keep it open until the final execve(). */
3461
3462 if (params->exec_fd >= 0) {
3463 exec_fd = params->exec_fd;
3464
3465 if (exec_fd < 3 + (int) n_fds) {
3466 int moved_fd;
3467
3468 /* Let's move the exec fd far up, so that it's outside of the fd range we want to pass to the
3469 * process we are about to execute. */
3470
3471 moved_fd = fcntl(exec_fd, F_DUPFD_CLOEXEC, 3 + (int) n_fds);
3472 if (moved_fd < 0) {
3473 *exit_status = EXIT_FDS;
3474 return log_unit_error_errno(unit, errno, "Couldn't move exec fd up: %m");
3475 }
3476
3477 safe_close(exec_fd);
3478 exec_fd = moved_fd;
3479 } else {
3480 /* This fd should be FD_CLOEXEC already, but let's make sure. */
3481 r = fd_cloexec(exec_fd, true);
3482 if (r < 0) {
3483 *exit_status = EXIT_FDS;
3484 return log_unit_error_errno(unit, r, "Failed to make exec fd FD_CLOEXEC: %m");
3485 }
3486 }
3487
3488 fds_with_exec_fd = newa(int, n_fds + 1);
7e8d494b 3489 memcpy_safe(fds_with_exec_fd, fds, n_fds * sizeof(int));
5686391b
LP
3490 fds_with_exec_fd[n_fds] = exec_fd;
3491 n_fds_with_exec_fd = n_fds + 1;
3492 } else {
3493 fds_with_exec_fd = fds;
3494 n_fds_with_exec_fd = n_fds;
3495 }
3496
3497 r = close_all_fds(fds_with_exec_fd, n_fds_with_exec_fd);
ff0af2a1
LP
3498 if (r >= 0)
3499 r = shift_fds(fds, n_fds);
3500 if (r >= 0)
25b583d7 3501 r = flags_fds(fds, n_socket_fds, n_storage_fds, context->non_blocking);
ff0af2a1
LP
3502 if (r < 0) {
3503 *exit_status = EXIT_FDS;
12145637 3504 return log_unit_error_errno(unit, r, "Failed to adjust passed file descriptors: %m");
d35fbf6b 3505 }
e66cf1a3 3506
5686391b
LP
3507 /* At this point, the fds we want to pass to the program are all ready and set up, with O_CLOEXEC turned off
3508 * and at the right fd numbers. The are no other fds open, with one exception: the exec_fd if it is defined,
3509 * and it has O_CLOEXEC set, after all we want it to be closed by the execve(), so that our parent knows we
3510 * came this far. */
3511
165a31c0 3512 secure_bits = context->secure_bits;
e66cf1a3 3513
165a31c0
LP
3514 if (needs_sandboxing) {
3515 uint64_t bset;
e66cf1a3 3516
ce932d2d
LP
3517 /* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly
3518 * requested. (Note this is placed after the general resource limit initialization, see
3519 * above, in order to take precedence.) */
f4170c67
LP
3520 if (context->restrict_realtime && !context->rlimit[RLIMIT_RTPRIO]) {
3521 if (setrlimit(RLIMIT_RTPRIO, &RLIMIT_MAKE_CONST(0)) < 0) {
3522 *exit_status = EXIT_LIMITS;
12145637 3523 return log_unit_error_errno(unit, errno, "Failed to adjust RLIMIT_RTPRIO resource limit: %m");
f4170c67
LP
3524 }
3525 }
3526
37ac2744
JB
3527#if ENABLE_SMACK
3528 /* LSM Smack needs the capability CAP_MAC_ADMIN to change the current execution security context of the
3529 * process. This is the latest place before dropping capabilities. Other MAC context are set later. */
3530 if (use_smack) {
3531 r = setup_smack(context, command);
3532 if (r < 0) {
3533 *exit_status = EXIT_SMACK_PROCESS_LABEL;
3534 return log_unit_error_errno(unit, r, "Failed to set SMACK process label: %m");
3535 }
3536 }
3537#endif
3538
165a31c0
LP
3539 bset = context->capability_bounding_set;
3540 /* If the ambient caps hack is enabled (which means the kernel can't do them, and the user asked for
3541 * our magic fallback), then let's add some extra caps, so that the service can drop privs of its own,
3542 * instead of us doing that */
3543 if (needs_ambient_hack)
3544 bset |= (UINT64_C(1) << CAP_SETPCAP) |
3545 (UINT64_C(1) << CAP_SETUID) |
3546 (UINT64_C(1) << CAP_SETGID);
3547
3548 if (!cap_test_all(bset)) {
3549 r = capability_bounding_set_drop(bset, false);
ff0af2a1
LP
3550 if (r < 0) {
3551 *exit_status = EXIT_CAPABILITIES;
12145637 3552 return log_unit_error_errno(unit, r, "Failed to drop capabilities: %m");
3b8bddde 3553 }
4c2630eb 3554 }
3b8bddde 3555
755d4b67
IP
3556 /* This is done before enforce_user, but ambient set
3557 * does not survive over setresuid() if keep_caps is not set. */
165a31c0
LP
3558 if (!needs_ambient_hack &&
3559 context->capability_ambient_set != 0) {
755d4b67
IP
3560 r = capability_ambient_set_apply(context->capability_ambient_set, true);
3561 if (r < 0) {
3562 *exit_status = EXIT_CAPABILITIES;
12145637 3563 return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (before UID change): %m");
755d4b67 3564 }
755d4b67 3565 }
165a31c0 3566 }
755d4b67 3567
fa97f630
JB
3568 /* chroot to root directory first, before we lose the ability to chroot */
3569 r = apply_root_directory(context, params, needs_mount_namespace, exit_status);
3570 if (r < 0)
3571 return log_unit_error_errno(unit, r, "Chrooting to the requested root directory failed: %m");
3572
165a31c0 3573 if (needs_setuid) {
08f67696 3574 if (uid_is_valid(uid)) {
ff0af2a1
LP
3575 r = enforce_user(context, uid);
3576 if (r < 0) {
3577 *exit_status = EXIT_USER;
12145637 3578 return log_unit_error_errno(unit, r, "Failed to change UID to " UID_FMT ": %m", uid);
5b6319dc 3579 }
165a31c0
LP
3580
3581 if (!needs_ambient_hack &&
3582 context->capability_ambient_set != 0) {
755d4b67
IP
3583
3584 /* Fix the ambient capabilities after user change. */
3585 r = capability_ambient_set_apply(context->capability_ambient_set, false);
3586 if (r < 0) {
3587 *exit_status = EXIT_CAPABILITIES;
12145637 3588 return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (after UID change): %m");
755d4b67
IP
3589 }
3590
3591 /* If we were asked to change user and ambient capabilities
3592 * were requested, we had to add keep-caps to the securebits
3593 * so that we would maintain the inherited capability set
3594 * through the setresuid(). Make sure that the bit is added
3595 * also to the context secure_bits so that we don't try to
3596 * drop the bit away next. */
3597
7f508f2c 3598 secure_bits |= 1<<SECURE_KEEP_CAPS;
755d4b67 3599 }
5b6319dc 3600 }
165a31c0 3601 }
d35fbf6b 3602
56ef8db9
JB
3603 /* Apply working directory here, because the working directory might be on NFS and only the user running
3604 * this service might have the correct privilege to change to the working directory */
fa97f630 3605 r = apply_working_directory(context, params, home, exit_status);
56ef8db9
JB
3606 if (r < 0)
3607 return log_unit_error_errno(unit, r, "Changing to the requested working directory failed: %m");
3608
165a31c0 3609 if (needs_sandboxing) {
37ac2744 3610 /* Apply other MAC contexts late, but before seccomp syscall filtering, as those should really be last to
5cd9cd35
LP
3611 * influence our own codepaths as little as possible. Moreover, applying MAC contexts usually requires
3612 * syscalls that are subject to seccomp filtering, hence should probably be applied before the syscalls
3613 * are restricted. */
3614
349cc4a5 3615#if HAVE_SELINUX
43b1f709 3616 if (use_selinux) {
5cd9cd35
LP
3617 char *exec_context = mac_selinux_context_net ?: context->selinux_context;
3618
3619 if (exec_context) {
3620 r = setexeccon(exec_context);
3621 if (r < 0) {
3622 *exit_status = EXIT_SELINUX_CONTEXT;
12145637 3623 return log_unit_error_errno(unit, r, "Failed to change SELinux context to %s: %m", exec_context);
5cd9cd35
LP
3624 }
3625 }
3626 }
3627#endif
3628
349cc4a5 3629#if HAVE_APPARMOR
43b1f709 3630 if (use_apparmor && context->apparmor_profile) {
5cd9cd35
LP
3631 r = aa_change_onexec(context->apparmor_profile);
3632 if (r < 0 && !context->apparmor_profile_ignore) {
3633 *exit_status = EXIT_APPARMOR_PROFILE;
12145637 3634 return log_unit_error_errno(unit, errno, "Failed to prepare AppArmor profile change to %s: %m", context->apparmor_profile);
5cd9cd35
LP
3635 }
3636 }
3637#endif
3638
165a31c0
LP
3639 /* PR_GET_SECUREBITS is not privileged, while PR_SET_SECUREBITS is. So to suppress potential EPERMs
3640 * we'll try not to call PR_SET_SECUREBITS unless necessary. */
755d4b67
IP
3641 if (prctl(PR_GET_SECUREBITS) != secure_bits)
3642 if (prctl(PR_SET_SECUREBITS, secure_bits) < 0) {
ff0af2a1 3643 *exit_status = EXIT_SECUREBITS;
12145637 3644 return log_unit_error_errno(unit, errno, "Failed to set process secure bits: %m");
ff01d048 3645 }
5b6319dc 3646
59eeb84b 3647 if (context_has_no_new_privileges(context))
d35fbf6b 3648 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
ff0af2a1 3649 *exit_status = EXIT_NO_NEW_PRIVILEGES;
12145637 3650 return log_unit_error_errno(unit, errno, "Failed to disable new privileges: %m");
d35fbf6b
DM
3651 }
3652
349cc4a5 3653#if HAVE_SECCOMP
469830d1
LP
3654 r = apply_address_families(unit, context);
3655 if (r < 0) {
3656 *exit_status = EXIT_ADDRESS_FAMILIES;
12145637 3657 return log_unit_error_errno(unit, r, "Failed to restrict address families: %m");
4c2630eb 3658 }
04aa0cb9 3659
469830d1
LP
3660 r = apply_memory_deny_write_execute(unit, context);
3661 if (r < 0) {
3662 *exit_status = EXIT_SECCOMP;
12145637 3663 return log_unit_error_errno(unit, r, "Failed to disable writing to executable memory: %m");
f3e43635 3664 }
f4170c67 3665
469830d1
LP
3666 r = apply_restrict_realtime(unit, context);
3667 if (r < 0) {
3668 *exit_status = EXIT_SECCOMP;
12145637 3669 return log_unit_error_errno(unit, r, "Failed to apply realtime restrictions: %m");
f4170c67
LP
3670 }
3671
f69567cb
LP
3672 r = apply_restrict_suid_sgid(unit, context);
3673 if (r < 0) {
3674 *exit_status = EXIT_SECCOMP;
3675 return log_unit_error_errno(unit, r, "Failed to apply SUID/SGID restrictions: %m");
3676 }
3677
add00535
LP
3678 r = apply_restrict_namespaces(unit, context);
3679 if (r < 0) {
3680 *exit_status = EXIT_SECCOMP;
12145637 3681 return log_unit_error_errno(unit, r, "Failed to apply namespace restrictions: %m");
add00535
LP
3682 }
3683
469830d1
LP
3684 r = apply_protect_sysctl(unit, context);
3685 if (r < 0) {
3686 *exit_status = EXIT_SECCOMP;
12145637 3687 return log_unit_error_errno(unit, r, "Failed to apply sysctl restrictions: %m");
502d704e
DH
3688 }
3689
469830d1
LP
3690 r = apply_protect_kernel_modules(unit, context);
3691 if (r < 0) {
3692 *exit_status = EXIT_SECCOMP;
12145637 3693 return log_unit_error_errno(unit, r, "Failed to apply module loading restrictions: %m");
59eeb84b
LP
3694 }
3695
84703040
KK
3696 r = apply_protect_kernel_logs(unit, context);
3697 if (r < 0) {
3698 *exit_status = EXIT_SECCOMP;
3699 return log_unit_error_errno(unit, r, "Failed to apply kernel log restrictions: %m");
3700 }
3701
469830d1
LP
3702 r = apply_private_devices(unit, context);
3703 if (r < 0) {
3704 *exit_status = EXIT_SECCOMP;
12145637 3705 return log_unit_error_errno(unit, r, "Failed to set up private devices: %m");
469830d1
LP
3706 }
3707
3708 r = apply_syscall_archs(unit, context);
3709 if (r < 0) {
3710 *exit_status = EXIT_SECCOMP;
12145637 3711 return log_unit_error_errno(unit, r, "Failed to apply syscall architecture restrictions: %m");
ba128bb8
LP
3712 }
3713
78e864e5
TM
3714 r = apply_lock_personality(unit, context);
3715 if (r < 0) {
3716 *exit_status = EXIT_SECCOMP;
12145637 3717 return log_unit_error_errno(unit, r, "Failed to lock personalities: %m");
78e864e5
TM
3718 }
3719
5cd9cd35
LP
3720 /* This really should remain the last step before the execve(), to make sure our own code is unaffected
3721 * by the filter as little as possible. */
165a31c0 3722 r = apply_syscall_filter(unit, context, needs_ambient_hack);
469830d1
LP
3723 if (r < 0) {
3724 *exit_status = EXIT_SECCOMP;
12145637 3725 return log_unit_error_errno(unit, r, "Failed to apply system call filters: %m");
d35fbf6b
DM
3726 }
3727#endif
d35fbf6b 3728 }
034c6ed7 3729
00819cc1
LP
3730 if (!strv_isempty(context->unset_environment)) {
3731 char **ee = NULL;
3732
3733 ee = strv_env_delete(accum_env, 1, context->unset_environment);
3734 if (!ee) {
3735 *exit_status = EXIT_MEMORY;
12145637 3736 return log_oom();
00819cc1
LP
3737 }
3738
130d3d22 3739 strv_free_and_replace(accum_env, ee);
00819cc1
LP
3740 }
3741
7ca69792
AZ
3742 if (!FLAGS_SET(command->flags, EXEC_COMMAND_NO_ENV_EXPAND)) {
3743 replaced_argv = replace_env_argv(command->argv, accum_env);
3744 if (!replaced_argv) {
3745 *exit_status = EXIT_MEMORY;
3746 return log_oom();
3747 }
3748 final_argv = replaced_argv;
3749 } else
3750 final_argv = command->argv;
034c6ed7 3751
f1d34068 3752 if (DEBUG_LOGGING) {
d35fbf6b 3753 _cleanup_free_ char *line;
81a2b7ce 3754
d35fbf6b 3755 line = exec_command_line(final_argv);
a1230ff9 3756 if (line)
f2341e0a 3757 log_struct(LOG_DEBUG,
f2341e0a
LP
3758 "EXECUTABLE=%s", command->path,
3759 LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
ba360bb0 3760 LOG_UNIT_ID(unit),
a1230ff9 3761 LOG_UNIT_INVOCATION_ID(unit));
d35fbf6b 3762 }
dd305ec9 3763
5686391b
LP
3764 if (exec_fd >= 0) {
3765 uint8_t hot = 1;
3766
3767 /* We have finished with all our initializations. Let's now let the manager know that. From this point
3768 * on, if the manager sees POLLHUP on the exec_fd, then execve() was successful. */
3769
3770 if (write(exec_fd, &hot, sizeof(hot)) < 0) {
3771 *exit_status = EXIT_EXEC;
3772 return log_unit_error_errno(unit, errno, "Failed to enable exec_fd: %m");
3773 }
3774 }
3775
2065ca69 3776 execve(command->path, final_argv, accum_env);
5686391b
LP
3777 r = -errno;
3778
3779 if (exec_fd >= 0) {
3780 uint8_t hot = 0;
3781
3782 /* The execve() failed. This means the exec_fd is still open. Which means we need to tell the manager
3783 * that POLLHUP on it no longer means execve() succeeded. */
3784
3785 if (write(exec_fd, &hot, sizeof(hot)) < 0) {
3786 *exit_status = EXIT_EXEC;
3787 return log_unit_error_errno(unit, errno, "Failed to disable exec_fd: %m");
3788 }
3789 }
12145637 3790
5686391b
LP
3791 if (r == -ENOENT && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
3792 log_struct_errno(LOG_INFO, r,
12145637
LP
3793 "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
3794 LOG_UNIT_ID(unit),
3795 LOG_UNIT_INVOCATION_ID(unit),
3796 LOG_UNIT_MESSAGE(unit, "Executable %s missing, skipping: %m",
3797 command->path),
a1230ff9 3798 "EXECUTABLE=%s", command->path);
12145637
LP
3799 return 0;
3800 }
3801
ff0af2a1 3802 *exit_status = EXIT_EXEC;
5686391b 3803 return log_unit_error_errno(unit, r, "Failed to execute command: %m");
d35fbf6b 3804}
81a2b7ce 3805
34cf6c43 3806static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l);
2caa38e9 3807static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[static 3]);
34cf6c43 3808
f2341e0a
LP
3809int exec_spawn(Unit *unit,
3810 ExecCommand *command,
d35fbf6b
DM
3811 const ExecContext *context,
3812 const ExecParameters *params,
3813 ExecRuntime *runtime,
29206d46 3814 DynamicCreds *dcreds,
d35fbf6b 3815 pid_t *ret) {
8351ceae 3816
ee39ca20 3817 int socket_fd, r, named_iofds[3] = { -1, -1, -1 }, *fds = NULL;
78f93209 3818 _cleanup_free_ char *subcgroup_path = NULL;
d35fbf6b 3819 _cleanup_strv_free_ char **files_env = NULL;
da6053d0 3820 size_t n_storage_fds = 0, n_socket_fds = 0;
ff0af2a1 3821 _cleanup_free_ char *line = NULL;
d35fbf6b 3822 pid_t pid;
8351ceae 3823
f2341e0a 3824 assert(unit);
d35fbf6b
DM
3825 assert(command);
3826 assert(context);
3827 assert(ret);
3828 assert(params);
25b583d7 3829 assert(params->fds || (params->n_socket_fds + params->n_storage_fds <= 0));
4298d0b5 3830
d35fbf6b
DM
3831 if (context->std_input == EXEC_INPUT_SOCKET ||
3832 context->std_output == EXEC_OUTPUT_SOCKET ||
3833 context->std_error == EXEC_OUTPUT_SOCKET) {
17df7223 3834
4c47affc 3835 if (params->n_socket_fds > 1) {
f2341e0a 3836 log_unit_error(unit, "Got more than one socket.");
d35fbf6b 3837 return -EINVAL;
ff0af2a1 3838 }
eef65bf3 3839
4c47affc 3840 if (params->n_socket_fds == 0) {
488ab41c
AA
3841 log_unit_error(unit, "Got no socket.");
3842 return -EINVAL;
3843 }
3844
d35fbf6b
DM
3845 socket_fd = params->fds[0];
3846 } else {
3847 socket_fd = -1;
3848 fds = params->fds;
9b141911 3849 n_socket_fds = params->n_socket_fds;
25b583d7 3850 n_storage_fds = params->n_storage_fds;
d35fbf6b 3851 }
94f04347 3852
34cf6c43 3853 r = exec_context_named_iofds(context, params, named_iofds);
52c239d7
LB
3854 if (r < 0)
3855 return log_unit_error_errno(unit, r, "Failed to load a named file descriptor: %m");
3856
f2341e0a 3857 r = exec_context_load_environment(unit, context, &files_env);
ff0af2a1 3858 if (r < 0)
f2341e0a 3859 return log_unit_error_errno(unit, r, "Failed to load environment files: %m");
034c6ed7 3860
ee39ca20 3861 line = exec_command_line(command->argv);
d35fbf6b
DM
3862 if (!line)
3863 return log_oom();
fab56fc5 3864
f2341e0a 3865 log_struct(LOG_DEBUG,
f2341e0a
LP
3866 LOG_UNIT_MESSAGE(unit, "About to execute: %s", line),
3867 "EXECUTABLE=%s", command->path,
ba360bb0 3868 LOG_UNIT_ID(unit),
a1230ff9 3869 LOG_UNIT_INVOCATION_ID(unit));
12145637 3870
78f93209
LP
3871 if (params->cgroup_path) {
3872 r = exec_parameters_get_cgroup_path(params, &subcgroup_path);
3873 if (r < 0)
3874 return log_unit_error_errno(unit, r, "Failed to acquire subcgroup path: %m");
3875 if (r > 0) { /* We are using a child cgroup */
3876 r = cg_create(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path);
3877 if (r < 0)
3878 return log_unit_error_errno(unit, r, "Failed to create control group '%s': %m", subcgroup_path);
3879 }
3880 }
3881
d35fbf6b
DM
3882 pid = fork();
3883 if (pid < 0)
74129a12 3884 return log_unit_error_errno(unit, errno, "Failed to fork: %m");
d35fbf6b
DM
3885
3886 if (pid == 0) {
12145637 3887 int exit_status = EXIT_SUCCESS;
ff0af2a1 3888
f2341e0a
LP
3889 r = exec_child(unit,
3890 command,
ff0af2a1
LP
3891 context,
3892 params,
3893 runtime,
29206d46 3894 dcreds,
ff0af2a1 3895 socket_fd,
52c239d7 3896 named_iofds,
4c47affc 3897 fds,
9b141911 3898 n_socket_fds,
25b583d7 3899 n_storage_fds,
ff0af2a1 3900 files_env,
00d9ef85 3901 unit->manager->user_lookup_fds[1],
12145637
LP
3902 &exit_status);
3903
e1714f02
ZJS
3904 if (r < 0) {
3905 const char *status =
3906 exit_status_to_string(exit_status,
e04ed6db 3907 EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
e1714f02 3908
12145637
LP
3909 log_struct_errno(LOG_ERR, r,
3910 "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
3911 LOG_UNIT_ID(unit),
3912 LOG_UNIT_INVOCATION_ID(unit),
3913 LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
e1714f02 3914 status, command->path),
a1230ff9 3915 "EXECUTABLE=%s", command->path);
e1714f02 3916 }
4c2630eb 3917
ff0af2a1 3918 _exit(exit_status);
034c6ed7
LP
3919 }
3920
f2341e0a 3921 log_unit_debug(unit, "Forked %s as "PID_FMT, command->path, pid);
23635a85 3922
78f93209
LP
3923 /* We add the new process to the cgroup both in the child (so that we can be sure that no user code is ever
3924 * executed outside of the cgroup) and in the parent (so that we can be sure that when we kill the cgroup the
3925 * process will be killed too). */
3926 if (subcgroup_path)
3927 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path, pid);
2da3263a 3928
b58b4116 3929 exec_status_start(&command->exec_status, pid);
9fb86720 3930
034c6ed7 3931 *ret = pid;
5cb5a6ff
LP
3932 return 0;
3933}
3934
034c6ed7 3935void exec_context_init(ExecContext *c) {
3536f49e
YW
3936 ExecDirectoryType i;
3937
034c6ed7
LP
3938 assert(c);
3939
4c12626c 3940 c->umask = 0022;
9eba9da4 3941 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
94f04347 3942 c->cpu_sched_policy = SCHED_OTHER;
071830ff 3943 c->syslog_priority = LOG_DAEMON|LOG_INFO;
74922904 3944 c->syslog_level_prefix = true;
353e12c2 3945 c->ignore_sigpipe = true;
3a43da28 3946 c->timer_slack_nsec = NSEC_INFINITY;
050f7277 3947 c->personality = PERSONALITY_INVALID;
72fd1768 3948 for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
3536f49e 3949 c->directories[i].mode = 0755;
12213aed 3950 c->timeout_clean_usec = USEC_INFINITY;
a103496c 3951 c->capability_bounding_set = CAP_ALL;
aa9d574d
YW
3952 assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL);
3953 c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL;
d3070fbd 3954 c->log_level_max = -1;
b070c7c0 3955 numa_policy_reset(&c->numa_policy);
034c6ed7
LP
3956}
3957
613b411c 3958void exec_context_done(ExecContext *c) {
3536f49e 3959 ExecDirectoryType i;
d3070fbd 3960 size_t l;
5cb5a6ff
LP
3961
3962 assert(c);
3963
6796073e
LP
3964 c->environment = strv_free(c->environment);
3965 c->environment_files = strv_free(c->environment_files);
b4c14404 3966 c->pass_environment = strv_free(c->pass_environment);
00819cc1 3967 c->unset_environment = strv_free(c->unset_environment);
8c7be95e 3968
31ce987c 3969 rlimit_free_all(c->rlimit);
034c6ed7 3970
2038c3f5 3971 for (l = 0; l < 3; l++) {
52c239d7 3972 c->stdio_fdname[l] = mfree(c->stdio_fdname[l]);
2038c3f5
LP
3973 c->stdio_file[l] = mfree(c->stdio_file[l]);
3974 }
52c239d7 3975
a1e58e8e
LP
3976 c->working_directory = mfree(c->working_directory);
3977 c->root_directory = mfree(c->root_directory);
915e6d16 3978 c->root_image = mfree(c->root_image);
a1e58e8e
LP
3979 c->tty_path = mfree(c->tty_path);
3980 c->syslog_identifier = mfree(c->syslog_identifier);
3981 c->user = mfree(c->user);
3982 c->group = mfree(c->group);
034c6ed7 3983
6796073e 3984 c->supplementary_groups = strv_free(c->supplementary_groups);
94f04347 3985
a1e58e8e 3986 c->pam_name = mfree(c->pam_name);
5b6319dc 3987
2a624c36
AP
3988 c->read_only_paths = strv_free(c->read_only_paths);
3989 c->read_write_paths = strv_free(c->read_write_paths);
3990 c->inaccessible_paths = strv_free(c->inaccessible_paths);
82c121a4 3991
d2d6c096 3992 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
8e06d57c
YW
3993 c->bind_mounts = NULL;
3994 c->n_bind_mounts = 0;
2abd4e38
YW
3995 temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems);
3996 c->temporary_filesystems = NULL;
3997 c->n_temporary_filesystems = 0;
d2d6c096 3998
0985c7c4 3999 cpu_set_reset(&c->cpu_set);
b070c7c0 4000 numa_policy_reset(&c->numa_policy);
86a3475b 4001
a1e58e8e
LP
4002 c->utmp_id = mfree(c->utmp_id);
4003 c->selinux_context = mfree(c->selinux_context);
4004 c->apparmor_profile = mfree(c->apparmor_profile);
5b8e1b77 4005 c->smack_process_label = mfree(c->smack_process_label);
eef65bf3 4006
8cfa775f 4007 c->syscall_filter = hashmap_free(c->syscall_filter);
525d3cc7
LP
4008 c->syscall_archs = set_free(c->syscall_archs);
4009 c->address_families = set_free(c->address_families);
e66cf1a3 4010
72fd1768 4011 for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
3536f49e 4012 c->directories[i].paths = strv_free(c->directories[i].paths);
d3070fbd
LP
4013
4014 c->log_level_max = -1;
4015
4016 exec_context_free_log_extra_fields(c);
08f3be7a 4017
5ac1530e
ZJS
4018 c->log_ratelimit_interval_usec = 0;
4019 c->log_ratelimit_burst = 0;
90fc172e 4020
08f3be7a
LP
4021 c->stdin_data = mfree(c->stdin_data);
4022 c->stdin_data_size = 0;
a8d08f39
LP
4023
4024 c->network_namespace_path = mfree(c->network_namespace_path);
e66cf1a3
LP
4025}
4026
34cf6c43 4027int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_prefix) {
e66cf1a3
LP
4028 char **i;
4029
4030 assert(c);
4031
4032 if (!runtime_prefix)
4033 return 0;
4034
3536f49e 4035 STRV_FOREACH(i, c->directories[EXEC_DIRECTORY_RUNTIME].paths) {
e66cf1a3
LP
4036 _cleanup_free_ char *p;
4037
494d0247
YW
4038 if (exec_directory_is_private(c, EXEC_DIRECTORY_RUNTIME))
4039 p = path_join(runtime_prefix, "private", *i);
4040 else
4041 p = path_join(runtime_prefix, *i);
e66cf1a3
LP
4042 if (!p)
4043 return -ENOMEM;
4044
7bc4bf4a
LP
4045 /* We execute this synchronously, since we need to be sure this is gone when we start the
4046 * service next. */
c6878637 4047 (void) rm_rf(p, REMOVE_ROOT);
e66cf1a3
LP
4048 }
4049
4050 return 0;
5cb5a6ff
LP
4051}
4052
34cf6c43 4053static void exec_command_done(ExecCommand *c) {
43d0fcbd
LP
4054 assert(c);
4055
a1e58e8e 4056 c->path = mfree(c->path);
6796073e 4057 c->argv = strv_free(c->argv);
43d0fcbd
LP
4058}
4059
da6053d0
LP
4060void exec_command_done_array(ExecCommand *c, size_t n) {
4061 size_t i;
43d0fcbd
LP
4062
4063 for (i = 0; i < n; i++)
4064 exec_command_done(c+i);
4065}
4066
f1acf85a 4067ExecCommand* exec_command_free_list(ExecCommand *c) {
5cb5a6ff
LP
4068 ExecCommand *i;
4069
4070 while ((i = c)) {
71fda00f 4071 LIST_REMOVE(command, c, i);
43d0fcbd 4072 exec_command_done(i);
5cb5a6ff
LP
4073 free(i);
4074 }
f1acf85a
ZJS
4075
4076 return NULL;
5cb5a6ff
LP
4077}
4078
da6053d0
LP
4079void exec_command_free_array(ExecCommand **c, size_t n) {
4080 size_t i;
034c6ed7 4081
f1acf85a
ZJS
4082 for (i = 0; i < n; i++)
4083 c[i] = exec_command_free_list(c[i]);
034c6ed7
LP
4084}
4085
6a1d4d9f
LP
4086void exec_command_reset_status_array(ExecCommand *c, size_t n) {
4087 size_t i;
4088
4089 for (i = 0; i < n; i++)
4090 exec_status_reset(&c[i].exec_status);
4091}
4092
4093void exec_command_reset_status_list_array(ExecCommand **c, size_t n) {
4094 size_t i;
4095
4096 for (i = 0; i < n; i++) {
4097 ExecCommand *z;
4098
4099 LIST_FOREACH(command, z, c[i])
4100 exec_status_reset(&z->exec_status);
4101 }
4102}
4103
039f0e70 4104typedef struct InvalidEnvInfo {
34cf6c43 4105 const Unit *unit;
039f0e70
LP
4106 const char *path;
4107} InvalidEnvInfo;
4108
4109static void invalid_env(const char *p, void *userdata) {
4110 InvalidEnvInfo *info = userdata;
4111
f2341e0a 4112 log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path);
039f0e70
LP
4113}
4114
52c239d7
LB
4115const char* exec_context_fdname(const ExecContext *c, int fd_index) {
4116 assert(c);
4117
4118 switch (fd_index) {
5073ff6b 4119
52c239d7
LB
4120 case STDIN_FILENO:
4121 if (c->std_input != EXEC_INPUT_NAMED_FD)
4122 return NULL;
5073ff6b 4123
52c239d7 4124 return c->stdio_fdname[STDIN_FILENO] ?: "stdin";
5073ff6b 4125
52c239d7
LB
4126 case STDOUT_FILENO:
4127 if (c->std_output != EXEC_OUTPUT_NAMED_FD)
4128 return NULL;
5073ff6b 4129
52c239d7 4130 return c->stdio_fdname[STDOUT_FILENO] ?: "stdout";
5073ff6b 4131
52c239d7
LB
4132 case STDERR_FILENO:
4133 if (c->std_error != EXEC_OUTPUT_NAMED_FD)
4134 return NULL;
5073ff6b 4135
52c239d7 4136 return c->stdio_fdname[STDERR_FILENO] ?: "stderr";
5073ff6b 4137
52c239d7
LB
4138 default:
4139 return NULL;
4140 }
4141}
4142
2caa38e9
LP
4143static int exec_context_named_iofds(
4144 const ExecContext *c,
4145 const ExecParameters *p,
4146 int named_iofds[static 3]) {
4147
da6053d0 4148 size_t i, targets;
56fbd561 4149 const char* stdio_fdname[3];
da6053d0 4150 size_t n_fds;
52c239d7
LB
4151
4152 assert(c);
4153 assert(p);
2caa38e9 4154 assert(named_iofds);
52c239d7
LB
4155
4156 targets = (c->std_input == EXEC_INPUT_NAMED_FD) +
4157 (c->std_output == EXEC_OUTPUT_NAMED_FD) +
4158 (c->std_error == EXEC_OUTPUT_NAMED_FD);
4159
4160 for (i = 0; i < 3; i++)
4161 stdio_fdname[i] = exec_context_fdname(c, i);
4162
4c47affc
FB
4163 n_fds = p->n_storage_fds + p->n_socket_fds;
4164
4165 for (i = 0; i < n_fds && targets > 0; i++)
56fbd561
ZJS
4166 if (named_iofds[STDIN_FILENO] < 0 &&
4167 c->std_input == EXEC_INPUT_NAMED_FD &&
4168 stdio_fdname[STDIN_FILENO] &&
4169 streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) {
4170
52c239d7
LB
4171 named_iofds[STDIN_FILENO] = p->fds[i];
4172 targets--;
56fbd561
ZJS
4173
4174 } else if (named_iofds[STDOUT_FILENO] < 0 &&
4175 c->std_output == EXEC_OUTPUT_NAMED_FD &&
4176 stdio_fdname[STDOUT_FILENO] &&
4177 streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) {
4178
52c239d7
LB
4179 named_iofds[STDOUT_FILENO] = p->fds[i];
4180 targets--;
56fbd561
ZJS
4181
4182 } else if (named_iofds[STDERR_FILENO] < 0 &&
4183 c->std_error == EXEC_OUTPUT_NAMED_FD &&
4184 stdio_fdname[STDERR_FILENO] &&
4185 streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) {
4186
52c239d7
LB
4187 named_iofds[STDERR_FILENO] = p->fds[i];
4188 targets--;
4189 }
4190
56fbd561 4191 return targets == 0 ? 0 : -ENOENT;
52c239d7
LB
4192}
4193
34cf6c43 4194static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l) {
8c7be95e
LP
4195 char **i, **r = NULL;
4196
4197 assert(c);
4198 assert(l);
4199
4200 STRV_FOREACH(i, c->environment_files) {
4201 char *fn;
52511fae
ZJS
4202 int k;
4203 unsigned n;
8c7be95e
LP
4204 bool ignore = false;
4205 char **p;
7fd1b19b 4206 _cleanup_globfree_ glob_t pglob = {};
8c7be95e
LP
4207
4208 fn = *i;
4209
4210 if (fn[0] == '-') {
4211 ignore = true;
313cefa1 4212 fn++;
8c7be95e
LP
4213 }
4214
4215 if (!path_is_absolute(fn)) {
8c7be95e
LP
4216 if (ignore)
4217 continue;
4218
4219 strv_free(r);
4220 return -EINVAL;
4221 }
4222
2bef10ab 4223 /* Filename supports globbing, take all matching files */
d8c92e8b
ZJS
4224 k = safe_glob(fn, 0, &pglob);
4225 if (k < 0) {
2bef10ab
PL
4226 if (ignore)
4227 continue;
8c7be95e 4228
2bef10ab 4229 strv_free(r);
d8c92e8b 4230 return k;
2bef10ab 4231 }
8c7be95e 4232
d8c92e8b
ZJS
4233 /* When we don't match anything, -ENOENT should be returned */
4234 assert(pglob.gl_pathc > 0);
4235
4236 for (n = 0; n < pglob.gl_pathc; n++) {
aa8fbc74 4237 k = load_env_file(NULL, pglob.gl_pathv[n], &p);
2bef10ab
PL
4238 if (k < 0) {
4239 if (ignore)
4240 continue;
8c7be95e 4241
2bef10ab 4242 strv_free(r);
2bef10ab 4243 return k;
e9c1ea9d 4244 }
ebc05a09 4245 /* Log invalid environment variables with filename */
039f0e70
LP
4246 if (p) {
4247 InvalidEnvInfo info = {
f2341e0a 4248 .unit = unit,
039f0e70
LP
4249 .path = pglob.gl_pathv[n]
4250 };
4251
4252 p = strv_env_clean_with_callback(p, invalid_env, &info);
4253 }
8c7be95e 4254
234519ae 4255 if (!r)
2bef10ab
PL
4256 r = p;
4257 else {
4258 char **m;
8c7be95e 4259
2bef10ab
PL
4260 m = strv_env_merge(2, r, p);
4261 strv_free(r);
4262 strv_free(p);
c84a9488 4263 if (!m)
2bef10ab 4264 return -ENOMEM;
2bef10ab
PL
4265
4266 r = m;
4267 }
8c7be95e
LP
4268 }
4269 }
4270
4271 *l = r;
4272
4273 return 0;
4274}
4275
6ac8fdc9 4276static bool tty_may_match_dev_console(const char *tty) {
7b912648 4277 _cleanup_free_ char *resolved = NULL;
6ac8fdc9 4278
1e22b5cd
LP
4279 if (!tty)
4280 return true;
4281
a119ec7c 4282 tty = skip_dev_prefix(tty);
6ac8fdc9
MS
4283
4284 /* trivial identity? */
4285 if (streq(tty, "console"))
4286 return true;
4287
7b912648
LP
4288 if (resolve_dev_console(&resolved) < 0)
4289 return true; /* if we could not resolve, assume it may */
6ac8fdc9
MS
4290
4291 /* "tty0" means the active VC, so it may be the same sometimes */
955f1c85 4292 return path_equal(resolved, tty) || (streq(resolved, "tty0") && tty_is_vc(tty));
6ac8fdc9
MS
4293}
4294
6c0ae739
LP
4295static bool exec_context_may_touch_tty(const ExecContext *ec) {
4296 assert(ec);
1e22b5cd 4297
6c0ae739 4298 return ec->tty_reset ||
1e22b5cd
LP
4299 ec->tty_vhangup ||
4300 ec->tty_vt_disallocate ||
6ac8fdc9
MS
4301 is_terminal_input(ec->std_input) ||
4302 is_terminal_output(ec->std_output) ||
6c0ae739
LP
4303 is_terminal_output(ec->std_error);
4304}
4305
4306bool exec_context_may_touch_console(const ExecContext *ec) {
4307
4308 return exec_context_may_touch_tty(ec) &&
1e22b5cd 4309 tty_may_match_dev_console(exec_context_tty_path(ec));
6ac8fdc9
MS
4310}
4311
15ae422b
LP
4312static void strv_fprintf(FILE *f, char **l) {
4313 char **g;
4314
4315 assert(f);
4316
4317 STRV_FOREACH(g, l)
4318 fprintf(f, " %s", *g);
4319}
4320
34cf6c43 4321void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
12213aed 4322 char **e, **d, buf_clean[FORMAT_TIMESPAN_MAX];
d3070fbd 4323 ExecDirectoryType dt;
94f04347 4324 unsigned i;
add00535 4325 int r;
9eba9da4 4326
5cb5a6ff
LP
4327 assert(c);
4328 assert(f);
4329
4ad49000 4330 prefix = strempty(prefix);
5cb5a6ff
LP
4331
4332 fprintf(f,
94f04347
LP
4333 "%sUMask: %04o\n"
4334 "%sWorkingDirectory: %s\n"
451a074f 4335 "%sRootDirectory: %s\n"
15ae422b 4336 "%sNonBlocking: %s\n"
64747e2d 4337 "%sPrivateTmp: %s\n"
7f112f50 4338 "%sPrivateDevices: %s\n"
59eeb84b 4339 "%sProtectKernelTunables: %s\n"
e66a2f65 4340 "%sProtectKernelModules: %s\n"
84703040 4341 "%sProtectKernelLogs: %s\n"
59eeb84b 4342 "%sProtectControlGroups: %s\n"
d251207d
LP
4343 "%sPrivateNetwork: %s\n"
4344 "%sPrivateUsers: %s\n"
1b8689f9
LP
4345 "%sProtectHome: %s\n"
4346 "%sProtectSystem: %s\n"
5d997827 4347 "%sMountAPIVFS: %s\n"
f3e43635 4348 "%sIgnoreSIGPIPE: %s\n"
f4170c67 4349 "%sMemoryDenyWriteExecute: %s\n"
b1edf445 4350 "%sRestrictRealtime: %s\n"
f69567cb 4351 "%sRestrictSUIDSGID: %s\n"
aecd5ac6
TM
4352 "%sKeyringMode: %s\n"
4353 "%sProtectHostname: %s\n",
5cb5a6ff 4354 prefix, c->umask,
9eba9da4 4355 prefix, c->working_directory ? c->working_directory : "/",
451a074f 4356 prefix, c->root_directory ? c->root_directory : "/",
15ae422b 4357 prefix, yes_no(c->non_blocking),
64747e2d 4358 prefix, yes_no(c->private_tmp),
7f112f50 4359 prefix, yes_no(c->private_devices),
59eeb84b 4360 prefix, yes_no(c->protect_kernel_tunables),
e66a2f65 4361 prefix, yes_no(c->protect_kernel_modules),
84703040 4362 prefix, yes_no(c->protect_kernel_logs),
59eeb84b 4363 prefix, yes_no(c->protect_control_groups),
d251207d
LP
4364 prefix, yes_no(c->private_network),
4365 prefix, yes_no(c->private_users),
1b8689f9
LP
4366 prefix, protect_home_to_string(c->protect_home),
4367 prefix, protect_system_to_string(c->protect_system),
5d997827 4368 prefix, yes_no(c->mount_apivfs),
f3e43635 4369 prefix, yes_no(c->ignore_sigpipe),
f4170c67 4370 prefix, yes_no(c->memory_deny_write_execute),
b1edf445 4371 prefix, yes_no(c->restrict_realtime),
f69567cb 4372 prefix, yes_no(c->restrict_suid_sgid),
aecd5ac6
TM
4373 prefix, exec_keyring_mode_to_string(c->keyring_mode),
4374 prefix, yes_no(c->protect_hostname));
fb33a393 4375
915e6d16
LP
4376 if (c->root_image)
4377 fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
4378
8c7be95e
LP
4379 STRV_FOREACH(e, c->environment)
4380 fprintf(f, "%sEnvironment: %s\n", prefix, *e);
4381
4382 STRV_FOREACH(e, c->environment_files)
4383 fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
94f04347 4384
b4c14404
FB
4385 STRV_FOREACH(e, c->pass_environment)
4386 fprintf(f, "%sPassEnvironment: %s\n", prefix, *e);
4387
00819cc1
LP
4388 STRV_FOREACH(e, c->unset_environment)
4389 fprintf(f, "%sUnsetEnvironment: %s\n", prefix, *e);
4390
53f47dfc
YW
4391 fprintf(f, "%sRuntimeDirectoryPreserve: %s\n", prefix, exec_preserve_mode_to_string(c->runtime_directory_preserve_mode));
4392
72fd1768 4393 for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) {
3536f49e
YW
4394 fprintf(f, "%s%sMode: %04o\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].mode);
4395
4396 STRV_FOREACH(d, c->directories[dt].paths)
4397 fprintf(f, "%s%s: %s\n", prefix, exec_directory_type_to_string(dt), *d);
4398 }
c2bbd90b 4399
12213aed
YW
4400 fprintf(f,
4401 "%sTimeoutCleanSec: %s\n",
4402 prefix, format_timespan(buf_clean, sizeof(buf_clean), c->timeout_clean_usec, USEC_PER_SEC));
4403
fb33a393
LP
4404 if (c->nice_set)
4405 fprintf(f,
4406 "%sNice: %i\n",
4407 prefix, c->nice);
4408
dd6c17b1 4409 if (c->oom_score_adjust_set)
fb33a393 4410 fprintf(f,
dd6c17b1
LP
4411 "%sOOMScoreAdjust: %i\n",
4412 prefix, c->oom_score_adjust);
9eba9da4 4413
94f04347 4414 for (i = 0; i < RLIM_NLIMITS; i++)
3c11da9d 4415 if (c->rlimit[i]) {
4c3a2b84 4416 fprintf(f, "%sLimit%s: " RLIM_FMT "\n",
3c11da9d 4417 prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
4c3a2b84 4418 fprintf(f, "%sLimit%sSoft: " RLIM_FMT "\n",
3c11da9d
EV
4419 prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur);
4420 }
94f04347 4421
f8b69d1d 4422 if (c->ioprio_set) {
1756a011 4423 _cleanup_free_ char *class_str = NULL;
f8b69d1d 4424
837df140
YW
4425 r = ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
4426 if (r >= 0)
4427 fprintf(f, "%sIOSchedulingClass: %s\n", prefix, class_str);
4428
4429 fprintf(f, "%sIOPriority: %lu\n", prefix, IOPRIO_PRIO_DATA(c->ioprio));
f8b69d1d 4430 }
94f04347 4431
f8b69d1d 4432 if (c->cpu_sched_set) {
1756a011 4433 _cleanup_free_ char *policy_str = NULL;
f8b69d1d 4434
837df140
YW
4435 r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
4436 if (r >= 0)
4437 fprintf(f, "%sCPUSchedulingPolicy: %s\n", prefix, policy_str);
4438
94f04347 4439 fprintf(f,
38b48754
LP
4440 "%sCPUSchedulingPriority: %i\n"
4441 "%sCPUSchedulingResetOnFork: %s\n",
38b48754
LP
4442 prefix, c->cpu_sched_priority,
4443 prefix, yes_no(c->cpu_sched_reset_on_fork));
b929bf04 4444 }
94f04347 4445
0985c7c4 4446 if (c->cpu_set.set) {
e7fca352
MS
4447 _cleanup_free_ char *affinity = NULL;
4448
4449 affinity = cpu_set_to_range_string(&c->cpu_set);
4450 fprintf(f, "%sCPUAffinity: %s\n", prefix, affinity);
94f04347
LP
4451 }
4452
b070c7c0
MS
4453 if (mpol_is_valid(numa_policy_get_type(&c->numa_policy))) {
4454 _cleanup_free_ char *nodes = NULL;
4455
4456 nodes = cpu_set_to_range_string(&c->numa_policy.nodes);
4457 fprintf(f, "%sNUMAPolicy: %s\n", prefix, mpol_to_string(numa_policy_get_type(&c->numa_policy)));
4458 fprintf(f, "%sNUMAMask: %s\n", prefix, strnull(nodes));
4459 }
4460
3a43da28 4461 if (c->timer_slack_nsec != NSEC_INFINITY)
ccd06097 4462 fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, c->timer_slack_nsec);
94f04347
LP
4463
4464 fprintf(f,
80876c20
LP
4465 "%sStandardInput: %s\n"
4466 "%sStandardOutput: %s\n"
4467 "%sStandardError: %s\n",
4468 prefix, exec_input_to_string(c->std_input),
4469 prefix, exec_output_to_string(c->std_output),
4470 prefix, exec_output_to_string(c->std_error));
4471
befc4a80
LP
4472 if (c->std_input == EXEC_INPUT_NAMED_FD)
4473 fprintf(f, "%sStandardInputFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDIN_FILENO]);
4474 if (c->std_output == EXEC_OUTPUT_NAMED_FD)
4475 fprintf(f, "%sStandardOutputFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDOUT_FILENO]);
4476 if (c->std_error == EXEC_OUTPUT_NAMED_FD)
4477 fprintf(f, "%sStandardErrorFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDERR_FILENO]);
4478
4479 if (c->std_input == EXEC_INPUT_FILE)
4480 fprintf(f, "%sStandardInputFile: %s\n", prefix, c->stdio_file[STDIN_FILENO]);
4481 if (c->std_output == EXEC_OUTPUT_FILE)
4482 fprintf(f, "%sStandardOutputFile: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
566b7d23
ZD
4483 if (c->std_output == EXEC_OUTPUT_FILE_APPEND)
4484 fprintf(f, "%sStandardOutputFileToAppend: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
befc4a80
LP
4485 if (c->std_error == EXEC_OUTPUT_FILE)
4486 fprintf(f, "%sStandardErrorFile: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
566b7d23
ZD
4487 if (c->std_error == EXEC_OUTPUT_FILE_APPEND)
4488 fprintf(f, "%sStandardErrorFileToAppend: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
befc4a80 4489
80876c20
LP
4490 if (c->tty_path)
4491 fprintf(f,
6ea832a2
LP
4492 "%sTTYPath: %s\n"
4493 "%sTTYReset: %s\n"
4494 "%sTTYVHangup: %s\n"
4495 "%sTTYVTDisallocate: %s\n",
4496 prefix, c->tty_path,
4497 prefix, yes_no(c->tty_reset),
4498 prefix, yes_no(c->tty_vhangup),
4499 prefix, yes_no(c->tty_vt_disallocate));
94f04347 4500
9f6444eb
LP
4501 if (IN_SET(c->std_output,
4502 EXEC_OUTPUT_SYSLOG,
4503 EXEC_OUTPUT_KMSG,
4504 EXEC_OUTPUT_JOURNAL,
4505 EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
4506 EXEC_OUTPUT_KMSG_AND_CONSOLE,
4507 EXEC_OUTPUT_JOURNAL_AND_CONSOLE) ||
4508 IN_SET(c->std_error,
4509 EXEC_OUTPUT_SYSLOG,
4510 EXEC_OUTPUT_KMSG,
4511 EXEC_OUTPUT_JOURNAL,
4512 EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
4513 EXEC_OUTPUT_KMSG_AND_CONSOLE,
4514 EXEC_OUTPUT_JOURNAL_AND_CONSOLE)) {
f8b69d1d 4515
5ce70e5b 4516 _cleanup_free_ char *fac_str = NULL, *lvl_str = NULL;
f8b69d1d 4517
837df140
YW
4518 r = log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
4519 if (r >= 0)
4520 fprintf(f, "%sSyslogFacility: %s\n", prefix, fac_str);
f8b69d1d 4521
837df140
YW
4522 r = log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
4523 if (r >= 0)
4524 fprintf(f, "%sSyslogLevel: %s\n", prefix, lvl_str);
f8b69d1d 4525 }
94f04347 4526
d3070fbd
LP
4527 if (c->log_level_max >= 0) {
4528 _cleanup_free_ char *t = NULL;
4529
4530 (void) log_level_to_string_alloc(c->log_level_max, &t);
4531
4532 fprintf(f, "%sLogLevelMax: %s\n", prefix, strna(t));
4533 }
4534
5ac1530e 4535 if (c->log_ratelimit_interval_usec > 0) {
90fc172e
AZ
4536 char buf_timespan[FORMAT_TIMESPAN_MAX];
4537
4538 fprintf(f,
4539 "%sLogRateLimitIntervalSec: %s\n",
5ac1530e 4540 prefix, format_timespan(buf_timespan, sizeof(buf_timespan), c->log_ratelimit_interval_usec, USEC_PER_SEC));
90fc172e
AZ
4541 }
4542
5ac1530e
ZJS
4543 if (c->log_ratelimit_burst > 0)
4544 fprintf(f, "%sLogRateLimitBurst: %u\n", prefix, c->log_ratelimit_burst);
90fc172e 4545
d3070fbd
LP
4546 if (c->n_log_extra_fields > 0) {
4547 size_t j;
4548
4549 for (j = 0; j < c->n_log_extra_fields; j++) {
4550 fprintf(f, "%sLogExtraFields: ", prefix);
4551 fwrite(c->log_extra_fields[j].iov_base,
4552 1, c->log_extra_fields[j].iov_len,
4553 f);
4554 fputc('\n', f);
4555 }
4556 }
4557
07d46372
YW
4558 if (c->secure_bits) {
4559 _cleanup_free_ char *str = NULL;
4560
4561 r = secure_bits_to_string_alloc(c->secure_bits, &str);
4562 if (r >= 0)
4563 fprintf(f, "%sSecure Bits: %s\n", prefix, str);
4564 }
94f04347 4565
a103496c 4566 if (c->capability_bounding_set != CAP_ALL) {
dd1f5bd0 4567 _cleanup_free_ char *str = NULL;
94f04347 4568
dd1f5bd0
YW
4569 r = capability_set_to_string_alloc(c->capability_bounding_set, &str);
4570 if (r >= 0)
4571 fprintf(f, "%sCapabilityBoundingSet: %s\n", prefix, str);
755d4b67
IP
4572 }
4573
4574 if (c->capability_ambient_set != 0) {
dd1f5bd0 4575 _cleanup_free_ char *str = NULL;
755d4b67 4576
dd1f5bd0
YW
4577 r = capability_set_to_string_alloc(c->capability_ambient_set, &str);
4578 if (r >= 0)
4579 fprintf(f, "%sAmbientCapabilities: %s\n", prefix, str);
94f04347
LP
4580 }
4581
4582 if (c->user)
f2d3769a 4583 fprintf(f, "%sUser: %s\n", prefix, c->user);
94f04347 4584 if (c->group)
f2d3769a 4585 fprintf(f, "%sGroup: %s\n", prefix, c->group);
94f04347 4586
29206d46
LP
4587 fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user));
4588
ac6e8be6 4589 if (!strv_isempty(c->supplementary_groups)) {
94f04347 4590 fprintf(f, "%sSupplementaryGroups:", prefix);
15ae422b
LP
4591 strv_fprintf(f, c->supplementary_groups);
4592 fputs("\n", f);
4593 }
94f04347 4594
5b6319dc 4595 if (c->pam_name)
f2d3769a 4596 fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
5b6319dc 4597
58629001 4598 if (!strv_isempty(c->read_write_paths)) {
2a624c36
AP
4599 fprintf(f, "%sReadWritePaths:", prefix);
4600 strv_fprintf(f, c->read_write_paths);
15ae422b
LP
4601 fputs("\n", f);
4602 }
4603
58629001 4604 if (!strv_isempty(c->read_only_paths)) {
2a624c36
AP
4605 fprintf(f, "%sReadOnlyPaths:", prefix);
4606 strv_fprintf(f, c->read_only_paths);
15ae422b
LP
4607 fputs("\n", f);
4608 }
94f04347 4609
58629001 4610 if (!strv_isempty(c->inaccessible_paths)) {
2a624c36
AP
4611 fprintf(f, "%sInaccessiblePaths:", prefix);
4612 strv_fprintf(f, c->inaccessible_paths);
94f04347
LP
4613 fputs("\n", f);
4614 }
2e22afe9 4615
d2d6c096 4616 if (c->n_bind_mounts > 0)
4ca763a9
YW
4617 for (i = 0; i < c->n_bind_mounts; i++)
4618 fprintf(f, "%s%s: %s%s:%s:%s\n", prefix,
d2d6c096 4619 c->bind_mounts[i].read_only ? "BindReadOnlyPaths" : "BindPaths",
4ca763a9 4620 c->bind_mounts[i].ignore_enoent ? "-": "",
d2d6c096
LP
4621 c->bind_mounts[i].source,
4622 c->bind_mounts[i].destination,
4623 c->bind_mounts[i].recursive ? "rbind" : "norbind");
d2d6c096 4624
2abd4e38
YW
4625 if (c->n_temporary_filesystems > 0)
4626 for (i = 0; i < c->n_temporary_filesystems; i++) {
4627 TemporaryFileSystem *t = c->temporary_filesystems + i;
4628
4629 fprintf(f, "%sTemporaryFileSystem: %s%s%s\n", prefix,
4630 t->path,
4631 isempty(t->options) ? "" : ":",
4632 strempty(t->options));
4633 }
4634
169c1bda
LP
4635 if (c->utmp_id)
4636 fprintf(f,
4637 "%sUtmpIdentifier: %s\n",
4638 prefix, c->utmp_id);
7b52a628
MS
4639
4640 if (c->selinux_context)
4641 fprintf(f,
5f8640fb
LP
4642 "%sSELinuxContext: %s%s\n",
4643 prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context);
17df7223 4644
80c21aea
WC
4645 if (c->apparmor_profile)
4646 fprintf(f,
4647 "%sAppArmorProfile: %s%s\n",
4648 prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile);
4649
4650 if (c->smack_process_label)
4651 fprintf(f,
4652 "%sSmackProcessLabel: %s%s\n",
4653 prefix, c->smack_process_label_ignore ? "-" : "", c->smack_process_label);
4654
050f7277 4655 if (c->personality != PERSONALITY_INVALID)
ac45f971
LP
4656 fprintf(f,
4657 "%sPersonality: %s\n",
4658 prefix, strna(personality_to_string(c->personality)));
4659
78e864e5
TM
4660 fprintf(f,
4661 "%sLockPersonality: %s\n",
4662 prefix, yes_no(c->lock_personality));
4663
17df7223 4664 if (c->syscall_filter) {
349cc4a5 4665#if HAVE_SECCOMP
17df7223 4666 Iterator j;
8cfa775f 4667 void *id, *val;
17df7223 4668 bool first = true;
351a19b1 4669#endif
17df7223
LP
4670
4671 fprintf(f,
57183d11 4672 "%sSystemCallFilter: ",
17df7223
LP
4673 prefix);
4674
4675 if (!c->syscall_whitelist)
4676 fputc('~', f);
4677
349cc4a5 4678#if HAVE_SECCOMP
8cfa775f 4679 HASHMAP_FOREACH_KEY(val, id, c->syscall_filter, j) {
17df7223 4680 _cleanup_free_ char *name = NULL;
8cfa775f
YW
4681 const char *errno_name = NULL;
4682 int num = PTR_TO_INT(val);
17df7223
LP
4683
4684 if (first)
4685 first = false;
4686 else
4687 fputc(' ', f);
4688
57183d11 4689 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
17df7223 4690 fputs(strna(name), f);
8cfa775f
YW
4691
4692 if (num >= 0) {
4693 errno_name = errno_to_name(num);
4694 if (errno_name)
4695 fprintf(f, ":%s", errno_name);
4696 else
4697 fprintf(f, ":%d", num);
4698 }
17df7223 4699 }
351a19b1 4700#endif
17df7223
LP
4701
4702 fputc('\n', f);
4703 }
4704
57183d11 4705 if (c->syscall_archs) {
349cc4a5 4706#if HAVE_SECCOMP
57183d11
LP
4707 Iterator j;
4708 void *id;
4709#endif
4710
4711 fprintf(f,
4712 "%sSystemCallArchitectures:",
4713 prefix);
4714
349cc4a5 4715#if HAVE_SECCOMP
57183d11
LP
4716 SET_FOREACH(id, c->syscall_archs, j)
4717 fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1)));
4718#endif
4719 fputc('\n', f);
4720 }
4721
add00535
LP
4722 if (exec_context_restrict_namespaces_set(c)) {
4723 _cleanup_free_ char *s = NULL;
4724
86c2a9f1 4725 r = namespace_flags_to_string(c->restrict_namespaces, &s);
add00535
LP
4726 if (r >= 0)
4727 fprintf(f, "%sRestrictNamespaces: %s\n",
4728 prefix, s);
4729 }
4730
a8d08f39
LP
4731 if (c->network_namespace_path)
4732 fprintf(f,
4733 "%sNetworkNamespacePath: %s\n",
4734 prefix, c->network_namespace_path);
4735
3df90f24
YW
4736 if (c->syscall_errno > 0) {
4737 const char *errno_name;
4738
4739 fprintf(f, "%sSystemCallErrorNumber: ", prefix);
4740
4741 errno_name = errno_to_name(c->syscall_errno);
4742 if (errno_name)
4743 fprintf(f, "%s\n", errno_name);
4744 else
4745 fprintf(f, "%d\n", c->syscall_errno);
4746 }
5cb5a6ff
LP
4747}
4748
34cf6c43 4749bool exec_context_maintains_privileges(const ExecContext *c) {
a931ad47
LP
4750 assert(c);
4751
61233823 4752 /* Returns true if the process forked off would run under
a931ad47
LP
4753 * an unchanged UID or as root. */
4754
4755 if (!c->user)
4756 return true;
4757
4758 if (streq(c->user, "root") || streq(c->user, "0"))
4759 return true;
4760
4761 return false;
4762}
4763
34cf6c43 4764int exec_context_get_effective_ioprio(const ExecContext *c) {
7f452159
LP
4765 int p;
4766
4767 assert(c);
4768
4769 if (c->ioprio_set)
4770 return c->ioprio;
4771
4772 p = ioprio_get(IOPRIO_WHO_PROCESS, 0);
4773 if (p < 0)
4774 return IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
4775
4776 return p;
4777}
4778
d3070fbd
LP
4779void exec_context_free_log_extra_fields(ExecContext *c) {
4780 size_t l;
4781
4782 assert(c);
4783
4784 for (l = 0; l < c->n_log_extra_fields; l++)
4785 free(c->log_extra_fields[l].iov_base);
4786 c->log_extra_fields = mfree(c->log_extra_fields);
4787 c->n_log_extra_fields = 0;
4788}
4789
6f765baf
LP
4790void exec_context_revert_tty(ExecContext *c) {
4791 int r;
4792
4793 assert(c);
4794
4795 /* First, reset the TTY (possibly kicking everybody else from the TTY) */
4796 exec_context_tty_reset(c, NULL);
4797
4798 /* And then undo what chown_terminal() did earlier. Note that we only do this if we have a path
4799 * configured. If the TTY was passed to us as file descriptor we assume the TTY is opened and managed
4800 * by whoever passed it to us and thus knows better when and how to chmod()/chown() it back. */
4801
4802 if (exec_context_may_touch_tty(c)) {
4803 const char *path;
4804
4805 path = exec_context_tty_path(c);
4806 if (path) {
4807 r = chmod_and_chown(path, TTY_MODE, 0, TTY_GID);
4808 if (r < 0 && r != -ENOENT)
4809 log_warning_errno(r, "Failed to reset TTY ownership/access mode of %s, ignoring: %m", path);
4810 }
4811 }
4812}
4813
4c2f5842
LP
4814int exec_context_get_clean_directories(
4815 ExecContext *c,
4816 char **prefix,
4817 ExecCleanMask mask,
4818 char ***ret) {
4819
4820 _cleanup_strv_free_ char **l = NULL;
4821 ExecDirectoryType t;
4822 int r;
4823
4824 assert(c);
4825 assert(prefix);
4826 assert(ret);
4827
4828 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
4829 char **i;
4830
4831 if (!FLAGS_SET(mask, 1U << t))
4832 continue;
4833
4834 if (!prefix[t])
4835 continue;
4836
4837 STRV_FOREACH(i, c->directories[t].paths) {
4838 char *j;
4839
4840 j = path_join(prefix[t], *i);
4841 if (!j)
4842 return -ENOMEM;
4843
4844 r = strv_consume(&l, j);
4845 if (r < 0)
4846 return r;
7f622a19
YW
4847
4848 /* Also remove private directories unconditionally. */
4849 if (t != EXEC_DIRECTORY_CONFIGURATION) {
4850 j = path_join(prefix[t], "private", *i);
4851 if (!j)
4852 return -ENOMEM;
4853
4854 r = strv_consume(&l, j);
4855 if (r < 0)
4856 return r;
4857 }
4c2f5842
LP
4858 }
4859 }
4860
4861 *ret = TAKE_PTR(l);
4862 return 0;
4863}
4864
4865int exec_context_get_clean_mask(ExecContext *c, ExecCleanMask *ret) {
4866 ExecCleanMask mask = 0;
4867
4868 assert(c);
4869 assert(ret);
4870
4871 for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++)
4872 if (!strv_isempty(c->directories[t].paths))
4873 mask |= 1U << t;
4874
4875 *ret = mask;
4876 return 0;
4877}
4878
b58b4116 4879void exec_status_start(ExecStatus *s, pid_t pid) {
034c6ed7 4880 assert(s);
5cb5a6ff 4881
2ed26ed0
LP
4882 *s = (ExecStatus) {
4883 .pid = pid,
4884 };
4885
b58b4116
LP
4886 dual_timestamp_get(&s->start_timestamp);
4887}
4888
34cf6c43 4889void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status) {
b58b4116
LP
4890 assert(s);
4891
2ed26ed0
LP
4892 if (s->pid != pid) {
4893 *s = (ExecStatus) {
4894 .pid = pid,
4895 };
4896 }
b58b4116 4897
63983207 4898 dual_timestamp_get(&s->exit_timestamp);
9fb86720 4899
034c6ed7
LP
4900 s->code = code;
4901 s->status = status;
169c1bda 4902
6f765baf
LP
4903 if (context && context->utmp_id)
4904 (void) utmp_put_dead_process(context->utmp_id, pid, code, status);
9fb86720
LP
4905}
4906
6a1d4d9f
LP
4907void exec_status_reset(ExecStatus *s) {
4908 assert(s);
4909
4910 *s = (ExecStatus) {};
4911}
4912
34cf6c43 4913void exec_status_dump(const ExecStatus *s, FILE *f, const char *prefix) {
9fb86720
LP
4914 char buf[FORMAT_TIMESTAMP_MAX];
4915
4916 assert(s);
4917 assert(f);
4918
9fb86720
LP
4919 if (s->pid <= 0)
4920 return;
4921
4c940960
LP
4922 prefix = strempty(prefix);
4923
9fb86720 4924 fprintf(f,
ccd06097
ZJS
4925 "%sPID: "PID_FMT"\n",
4926 prefix, s->pid);
9fb86720 4927
af9d16e1 4928 if (dual_timestamp_is_set(&s->start_timestamp))
9fb86720
LP
4929 fprintf(f,
4930 "%sStart Timestamp: %s\n",
63983207 4931 prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
9fb86720 4932
af9d16e1 4933 if (dual_timestamp_is_set(&s->exit_timestamp))
9fb86720
LP
4934 fprintf(f,
4935 "%sExit Timestamp: %s\n"
4936 "%sExit Code: %s\n"
4937 "%sExit Status: %i\n",
63983207 4938 prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
9fb86720
LP
4939 prefix, sigchld_code_to_string(s->code),
4940 prefix, s->status);
5cb5a6ff 4941}
44d8db9e 4942
34cf6c43 4943static char *exec_command_line(char **argv) {
44d8db9e
LP
4944 size_t k;
4945 char *n, *p, **a;
4946 bool first = true;
4947
9e2f7c11 4948 assert(argv);
44d8db9e 4949
9164977d 4950 k = 1;
9e2f7c11 4951 STRV_FOREACH(a, argv)
44d8db9e
LP
4952 k += strlen(*a)+3;
4953
5cd9cd35
LP
4954 n = new(char, k);
4955 if (!n)
44d8db9e
LP
4956 return NULL;
4957
4958 p = n;
9e2f7c11 4959 STRV_FOREACH(a, argv) {
44d8db9e
LP
4960
4961 if (!first)
4962 *(p++) = ' ';
4963 else
4964 first = false;
4965
4966 if (strpbrk(*a, WHITESPACE)) {
4967 *(p++) = '\'';
4968 p = stpcpy(p, *a);
4969 *(p++) = '\'';
4970 } else
4971 p = stpcpy(p, *a);
4972
4973 }
4974
9164977d
LP
4975 *p = 0;
4976
44d8db9e
LP
4977 /* FIXME: this doesn't really handle arguments that have
4978 * spaces and ticks in them */
4979
4980 return n;
4981}
4982
34cf6c43 4983static void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
e1d75803 4984 _cleanup_free_ char *cmd = NULL;
4c940960 4985 const char *prefix2;
44d8db9e
LP
4986
4987 assert(c);
4988 assert(f);
4989
4c940960 4990 prefix = strempty(prefix);
63c372cb 4991 prefix2 = strjoina(prefix, "\t");
44d8db9e 4992
9e2f7c11 4993 cmd = exec_command_line(c->argv);
44d8db9e
LP
4994 fprintf(f,
4995 "%sCommand Line: %s\n",
4bbccb02 4996 prefix, cmd ? cmd : strerror_safe(ENOMEM));
44d8db9e 4997
9fb86720 4998 exec_status_dump(&c->exec_status, f, prefix2);
44d8db9e
LP
4999}
5000
5001void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
5002 assert(f);
5003
4c940960 5004 prefix = strempty(prefix);
44d8db9e
LP
5005
5006 LIST_FOREACH(command, c, c)
5007 exec_command_dump(c, f, prefix);
5008}
94f04347 5009
a6a80b4f
LP
5010void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
5011 ExecCommand *end;
5012
5013 assert(l);
5014 assert(e);
5015
5016 if (*l) {
35b8ca3a 5017 /* It's kind of important, that we keep the order here */
71fda00f
LP
5018 LIST_FIND_TAIL(command, *l, end);
5019 LIST_INSERT_AFTER(command, *l, end, e);
a6a80b4f
LP
5020 } else
5021 *l = e;
5022}
5023
26fd040d
LP
5024int exec_command_set(ExecCommand *c, const char *path, ...) {
5025 va_list ap;
5026 char **l, *p;
5027
5028 assert(c);
5029 assert(path);
5030
5031 va_start(ap, path);
5032 l = strv_new_ap(path, ap);
5033 va_end(ap);
5034
5035 if (!l)
5036 return -ENOMEM;
5037
250a918d
LP
5038 p = strdup(path);
5039 if (!p) {
26fd040d
LP
5040 strv_free(l);
5041 return -ENOMEM;
5042 }
5043
6897dfe8 5044 free_and_replace(c->path, p);
26fd040d 5045
130d3d22 5046 return strv_free_and_replace(c->argv, l);
26fd040d
LP
5047}
5048
86b23b07 5049int exec_command_append(ExecCommand *c, const char *path, ...) {
e63ff941 5050 _cleanup_strv_free_ char **l = NULL;
86b23b07 5051 va_list ap;
86b23b07
JS
5052 int r;
5053
5054 assert(c);
5055 assert(path);
5056
5057 va_start(ap, path);
5058 l = strv_new_ap(path, ap);
5059 va_end(ap);
5060
5061 if (!l)
5062 return -ENOMEM;
5063
e287086b 5064 r = strv_extend_strv(&c->argv, l, false);
e63ff941 5065 if (r < 0)
86b23b07 5066 return r;
86b23b07
JS
5067
5068 return 0;
5069}
5070
e8a565cb
YW
5071static void *remove_tmpdir_thread(void *p) {
5072 _cleanup_free_ char *path = p;
86b23b07 5073
e8a565cb
YW
5074 (void) rm_rf(path, REMOVE_ROOT|REMOVE_PHYSICAL);
5075 return NULL;
5076}
5077
5078static ExecRuntime* exec_runtime_free(ExecRuntime *rt, bool destroy) {
5079 int r;
5080
5081 if (!rt)
5082 return NULL;
5083
5084 if (rt->manager)
5085 (void) hashmap_remove(rt->manager->exec_runtime_by_id, rt->id);
5086
5087 /* When destroy is true, then rm_rf tmp_dir and var_tmp_dir. */
5088 if (destroy && rt->tmp_dir) {
5089 log_debug("Spawning thread to nuke %s", rt->tmp_dir);
5090
5091 r = asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
5092 if (r < 0) {
5093 log_warning_errno(r, "Failed to nuke %s: %m", rt->tmp_dir);
5094 free(rt->tmp_dir);
5095 }
5096
5097 rt->tmp_dir = NULL;
5098 }
613b411c 5099
e8a565cb
YW
5100 if (destroy && rt->var_tmp_dir) {
5101 log_debug("Spawning thread to nuke %s", rt->var_tmp_dir);
5102
5103 r = asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
5104 if (r < 0) {
5105 log_warning_errno(r, "Failed to nuke %s: %m", rt->var_tmp_dir);
5106 free(rt->var_tmp_dir);
5107 }
5108
5109 rt->var_tmp_dir = NULL;
5110 }
5111
5112 rt->id = mfree(rt->id);
5113 rt->tmp_dir = mfree(rt->tmp_dir);
5114 rt->var_tmp_dir = mfree(rt->var_tmp_dir);
5115 safe_close_pair(rt->netns_storage_socket);
5116 return mfree(rt);
5117}
5118
5119static void exec_runtime_freep(ExecRuntime **rt) {
da6bc6ed 5120 (void) exec_runtime_free(*rt, false);
e8a565cb
YW
5121}
5122
8e8009dc
LP
5123static int exec_runtime_allocate(ExecRuntime **ret) {
5124 ExecRuntime *n;
613b411c 5125
8e8009dc 5126 assert(ret);
613b411c 5127
8e8009dc
LP
5128 n = new(ExecRuntime, 1);
5129 if (!n)
613b411c
LP
5130 return -ENOMEM;
5131
8e8009dc
LP
5132 *n = (ExecRuntime) {
5133 .netns_storage_socket = { -1, -1 },
5134 };
5135
5136 *ret = n;
613b411c
LP
5137 return 0;
5138}
5139
e8a565cb
YW
5140static int exec_runtime_add(
5141 Manager *m,
5142 const char *id,
5143 const char *tmp_dir,
5144 const char *var_tmp_dir,
5145 const int netns_storage_socket[2],
5146 ExecRuntime **ret) {
5147
5148 _cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL;
613b411c
LP
5149 int r;
5150
e8a565cb 5151 assert(m);
613b411c
LP
5152 assert(id);
5153
e8a565cb
YW
5154 r = hashmap_ensure_allocated(&m->exec_runtime_by_id, &string_hash_ops);
5155 if (r < 0)
5156 return r;
613b411c 5157
e8a565cb 5158 r = exec_runtime_allocate(&rt);
613b411c
LP
5159 if (r < 0)
5160 return r;
5161
e8a565cb
YW
5162 rt->id = strdup(id);
5163 if (!rt->id)
5164 return -ENOMEM;
5165
5166 if (tmp_dir) {
5167 rt->tmp_dir = strdup(tmp_dir);
5168 if (!rt->tmp_dir)
5169 return -ENOMEM;
5170
5171 /* When tmp_dir is set, then we require var_tmp_dir is also set. */
5172 assert(var_tmp_dir);
5173 rt->var_tmp_dir = strdup(var_tmp_dir);
5174 if (!rt->var_tmp_dir)
5175 return -ENOMEM;
5176 }
5177
5178 if (netns_storage_socket) {
5179 rt->netns_storage_socket[0] = netns_storage_socket[0];
5180 rt->netns_storage_socket[1] = netns_storage_socket[1];
613b411c
LP
5181 }
5182
e8a565cb
YW
5183 r = hashmap_put(m->exec_runtime_by_id, rt->id, rt);
5184 if (r < 0)
5185 return r;
5186
5187 rt->manager = m;
5188
5189 if (ret)
5190 *ret = rt;
5191
5192 /* do not remove created ExecRuntime object when the operation succeeds. */
5193 rt = NULL;
5194 return 0;
5195}
5196
5197static int exec_runtime_make(Manager *m, const ExecContext *c, const char *id, ExecRuntime **ret) {
5198 _cleanup_free_ char *tmp_dir = NULL, *var_tmp_dir = NULL;
2fa3742d 5199 _cleanup_close_pair_ int netns_storage_socket[2] = { -1, -1 };
e8a565cb
YW
5200 int r;
5201
5202 assert(m);
5203 assert(c);
5204 assert(id);
5205
5206 /* It is not necessary to create ExecRuntime object. */
a8d08f39 5207 if (!c->private_network && !c->private_tmp && !c->network_namespace_path)
e8a565cb
YW
5208 return 0;
5209
5210 if (c->private_tmp) {
5211 r = setup_tmp_dirs(id, &tmp_dir, &var_tmp_dir);
613b411c
LP
5212 if (r < 0)
5213 return r;
5214 }
5215
a8d08f39 5216 if (c->private_network || c->network_namespace_path) {
e8a565cb
YW
5217 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, netns_storage_socket) < 0)
5218 return -errno;
5219 }
5220
5221 r = exec_runtime_add(m, id, tmp_dir, var_tmp_dir, netns_storage_socket, ret);
5222 if (r < 0)
5223 return r;
5224
5225 /* Avoid cleanup */
2fa3742d 5226 netns_storage_socket[0] = netns_storage_socket[1] = -1;
613b411c
LP
5227 return 1;
5228}
5229
e8a565cb
YW
5230int exec_runtime_acquire(Manager *m, const ExecContext *c, const char *id, bool create, ExecRuntime **ret) {
5231 ExecRuntime *rt;
5232 int r;
613b411c 5233
e8a565cb
YW
5234 assert(m);
5235 assert(id);
5236 assert(ret);
5237
5238 rt = hashmap_get(m->exec_runtime_by_id, id);
5239 if (rt)
5240 /* We already have a ExecRuntime object, let's increase the ref count and reuse it */
5241 goto ref;
5242
5243 if (!create)
5244 return 0;
5245
5246 /* If not found, then create a new object. */
5247 r = exec_runtime_make(m, c, id, &rt);
5248 if (r <= 0)
5249 /* When r == 0, it is not necessary to create ExecRuntime object. */
5250 return r;
613b411c 5251
e8a565cb
YW
5252ref:
5253 /* increment reference counter. */
5254 rt->n_ref++;
5255 *ret = rt;
5256 return 1;
5257}
613b411c 5258
e8a565cb
YW
5259ExecRuntime *exec_runtime_unref(ExecRuntime *rt, bool destroy) {
5260 if (!rt)
613b411c
LP
5261 return NULL;
5262
e8a565cb 5263 assert(rt->n_ref > 0);
613b411c 5264
e8a565cb
YW
5265 rt->n_ref--;
5266 if (rt->n_ref > 0)
f2341e0a
LP
5267 return NULL;
5268
e8a565cb 5269 return exec_runtime_free(rt, destroy);
613b411c
LP
5270}
5271
e8a565cb
YW
5272int exec_runtime_serialize(const Manager *m, FILE *f, FDSet *fds) {
5273 ExecRuntime *rt;
5274 Iterator i;
5275
5276 assert(m);
613b411c
LP
5277 assert(f);
5278 assert(fds);
5279
e8a565cb
YW
5280 HASHMAP_FOREACH(rt, m->exec_runtime_by_id, i) {
5281 fprintf(f, "exec-runtime=%s", rt->id);
613b411c 5282
e8a565cb
YW
5283 if (rt->tmp_dir)
5284 fprintf(f, " tmp-dir=%s", rt->tmp_dir);
613b411c 5285
e8a565cb
YW
5286 if (rt->var_tmp_dir)
5287 fprintf(f, " var-tmp-dir=%s", rt->var_tmp_dir);
613b411c 5288
e8a565cb
YW
5289 if (rt->netns_storage_socket[0] >= 0) {
5290 int copy;
613b411c 5291
e8a565cb
YW
5292 copy = fdset_put_dup(fds, rt->netns_storage_socket[0]);
5293 if (copy < 0)
5294 return copy;
613b411c 5295
e8a565cb
YW
5296 fprintf(f, " netns-socket-0=%i", copy);
5297 }
613b411c 5298
e8a565cb
YW
5299 if (rt->netns_storage_socket[1] >= 0) {
5300 int copy;
613b411c 5301
e8a565cb
YW
5302 copy = fdset_put_dup(fds, rt->netns_storage_socket[1]);
5303 if (copy < 0)
5304 return copy;
613b411c 5305
e8a565cb
YW
5306 fprintf(f, " netns-socket-1=%i", copy);
5307 }
5308
5309 fputc('\n', f);
613b411c
LP
5310 }
5311
5312 return 0;
5313}
5314
e8a565cb
YW
5315int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value, FDSet *fds) {
5316 _cleanup_(exec_runtime_freep) ExecRuntime *rt_create = NULL;
5317 ExecRuntime *rt;
613b411c
LP
5318 int r;
5319
e8a565cb
YW
5320 /* This is for the migration from old (v237 or earlier) deserialization text.
5321 * Due to the bug #7790, this may not work with the units that use JoinsNamespaceOf=.
5322 * Even if the ExecRuntime object originally created by the other unit, we cannot judge
5323 * so or not from the serialized text, then we always creates a new object owned by this. */
5324
5325 assert(u);
613b411c
LP
5326 assert(key);
5327 assert(value);
5328
e8a565cb
YW
5329 /* Manager manages ExecRuntime objects by the unit id.
5330 * So, we omit the serialized text when the unit does not have id (yet?)... */
5331 if (isempty(u->id)) {
5332 log_unit_debug(u, "Invocation ID not found. Dropping runtime parameter.");
5333 return 0;
5334 }
613b411c 5335
e8a565cb
YW
5336 r = hashmap_ensure_allocated(&u->manager->exec_runtime_by_id, &string_hash_ops);
5337 if (r < 0) {
5338 log_unit_debug_errno(u, r, "Failed to allocate storage for runtime parameter: %m");
5339 return 0;
5340 }
5341
5342 rt = hashmap_get(u->manager->exec_runtime_by_id, u->id);
5343 if (!rt) {
5344 r = exec_runtime_allocate(&rt_create);
613b411c 5345 if (r < 0)
f2341e0a 5346 return log_oom();
613b411c 5347
e8a565cb
YW
5348 rt_create->id = strdup(u->id);
5349 if (!rt_create->id)
5350 return log_oom();
5351
5352 rt = rt_create;
5353 }
5354
5355 if (streq(key, "tmp-dir")) {
5356 char *copy;
5357
613b411c
LP
5358 copy = strdup(value);
5359 if (!copy)
5360 return log_oom();
5361
e8a565cb 5362 free_and_replace(rt->tmp_dir, copy);
613b411c
LP
5363
5364 } else if (streq(key, "var-tmp-dir")) {
5365 char *copy;
5366
613b411c
LP
5367 copy = strdup(value);
5368 if (!copy)
5369 return log_oom();
5370
e8a565cb 5371 free_and_replace(rt->var_tmp_dir, copy);
613b411c
LP
5372
5373 } else if (streq(key, "netns-socket-0")) {
5374 int fd;
5375
e8a565cb 5376 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
f2341e0a 5377 log_unit_debug(u, "Failed to parse netns socket value: %s", value);
e8a565cb 5378 return 0;
613b411c 5379 }
e8a565cb
YW
5380
5381 safe_close(rt->netns_storage_socket[0]);
5382 rt->netns_storage_socket[0] = fdset_remove(fds, fd);
5383
613b411c
LP
5384 } else if (streq(key, "netns-socket-1")) {
5385 int fd;
5386
e8a565cb 5387 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
f2341e0a 5388 log_unit_debug(u, "Failed to parse netns socket value: %s", value);
e8a565cb 5389 return 0;
613b411c 5390 }
e8a565cb
YW
5391
5392 safe_close(rt->netns_storage_socket[1]);
5393 rt->netns_storage_socket[1] = fdset_remove(fds, fd);
613b411c
LP
5394 } else
5395 return 0;
5396
e8a565cb
YW
5397 /* If the object is newly created, then put it to the hashmap which manages ExecRuntime objects. */
5398 if (rt_create) {
5399 r = hashmap_put(u->manager->exec_runtime_by_id, rt_create->id, rt_create);
5400 if (r < 0) {
3fe91079 5401 log_unit_debug_errno(u, r, "Failed to put runtime parameter to manager's storage: %m");
e8a565cb
YW
5402 return 0;
5403 }
613b411c 5404
e8a565cb 5405 rt_create->manager = u->manager;
613b411c 5406
e8a565cb
YW
5407 /* Avoid cleanup */
5408 rt_create = NULL;
5409 }
98b47d54 5410
e8a565cb
YW
5411 return 1;
5412}
613b411c 5413
e8a565cb
YW
5414void exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
5415 char *id = NULL, *tmp_dir = NULL, *var_tmp_dir = NULL;
5416 int r, fd0 = -1, fd1 = -1;
5417 const char *p, *v = value;
5418 size_t n;
613b411c 5419
e8a565cb
YW
5420 assert(m);
5421 assert(value);
5422 assert(fds);
98b47d54 5423
e8a565cb
YW
5424 n = strcspn(v, " ");
5425 id = strndupa(v, n);
5426 if (v[n] != ' ')
5427 goto finalize;
5428 p = v + n + 1;
5429
5430 v = startswith(p, "tmp-dir=");
5431 if (v) {
5432 n = strcspn(v, " ");
5433 tmp_dir = strndupa(v, n);
5434 if (v[n] != ' ')
5435 goto finalize;
5436 p = v + n + 1;
5437 }
5438
5439 v = startswith(p, "var-tmp-dir=");
5440 if (v) {
5441 n = strcspn(v, " ");
5442 var_tmp_dir = strndupa(v, n);
5443 if (v[n] != ' ')
5444 goto finalize;
5445 p = v + n + 1;
5446 }
5447
5448 v = startswith(p, "netns-socket-0=");
5449 if (v) {
5450 char *buf;
5451
5452 n = strcspn(v, " ");
5453 buf = strndupa(v, n);
5454 if (safe_atoi(buf, &fd0) < 0 || !fdset_contains(fds, fd0)) {
5455 log_debug("Unable to process exec-runtime netns fd specification.");
5456 return;
98b47d54 5457 }
e8a565cb
YW
5458 fd0 = fdset_remove(fds, fd0);
5459 if (v[n] != ' ')
5460 goto finalize;
5461 p = v + n + 1;
613b411c
LP
5462 }
5463
e8a565cb
YW
5464 v = startswith(p, "netns-socket-1=");
5465 if (v) {
5466 char *buf;
98b47d54 5467
e8a565cb
YW
5468 n = strcspn(v, " ");
5469 buf = strndupa(v, n);
5470 if (safe_atoi(buf, &fd1) < 0 || !fdset_contains(fds, fd1)) {
5471 log_debug("Unable to process exec-runtime netns fd specification.");
5472 return;
98b47d54 5473 }
e8a565cb
YW
5474 fd1 = fdset_remove(fds, fd1);
5475 }
98b47d54 5476
e8a565cb
YW
5477finalize:
5478
5479 r = exec_runtime_add(m, id, tmp_dir, var_tmp_dir, (int[]) { fd0, fd1 }, NULL);
7d853ca6 5480 if (r < 0)
e8a565cb 5481 log_debug_errno(r, "Failed to add exec-runtime: %m");
e8a565cb 5482}
613b411c 5483
e8a565cb
YW
5484void exec_runtime_vacuum(Manager *m) {
5485 ExecRuntime *rt;
5486 Iterator i;
5487
5488 assert(m);
5489
5490 /* Free unreferenced ExecRuntime objects. This is used after manager deserialization process. */
5491
5492 HASHMAP_FOREACH(rt, m->exec_runtime_by_id, i) {
5493 if (rt->n_ref > 0)
5494 continue;
5495
5496 (void) exec_runtime_free(rt, false);
5497 }
613b411c
LP
5498}
5499
b9c04eaf
YW
5500void exec_params_clear(ExecParameters *p) {
5501 if (!p)
5502 return;
5503
5504 strv_free(p->environment);
5505}
5506
80876c20
LP
5507static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
5508 [EXEC_INPUT_NULL] = "null",
5509 [EXEC_INPUT_TTY] = "tty",
5510 [EXEC_INPUT_TTY_FORCE] = "tty-force",
4f2d528d 5511 [EXEC_INPUT_TTY_FAIL] = "tty-fail",
52c239d7
LB
5512 [EXEC_INPUT_SOCKET] = "socket",
5513 [EXEC_INPUT_NAMED_FD] = "fd",
08f3be7a 5514 [EXEC_INPUT_DATA] = "data",
2038c3f5 5515 [EXEC_INPUT_FILE] = "file",
80876c20
LP
5516};
5517
8a0867d6
LP
5518DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
5519
94f04347 5520static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
80876c20 5521 [EXEC_OUTPUT_INHERIT] = "inherit",
94f04347 5522 [EXEC_OUTPUT_NULL] = "null",
80876c20 5523 [EXEC_OUTPUT_TTY] = "tty",
94f04347 5524 [EXEC_OUTPUT_SYSLOG] = "syslog",
28dbc1e8 5525 [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
9a6bca7a 5526 [EXEC_OUTPUT_KMSG] = "kmsg",
28dbc1e8 5527 [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
706343f4
LP
5528 [EXEC_OUTPUT_JOURNAL] = "journal",
5529 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
52c239d7
LB
5530 [EXEC_OUTPUT_SOCKET] = "socket",
5531 [EXEC_OUTPUT_NAMED_FD] = "fd",
2038c3f5 5532 [EXEC_OUTPUT_FILE] = "file",
566b7d23 5533 [EXEC_OUTPUT_FILE_APPEND] = "append",
94f04347
LP
5534};
5535
5536DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
023a4f67
LP
5537
5538static const char* const exec_utmp_mode_table[_EXEC_UTMP_MODE_MAX] = {
5539 [EXEC_UTMP_INIT] = "init",
5540 [EXEC_UTMP_LOGIN] = "login",
5541 [EXEC_UTMP_USER] = "user",
5542};
5543
5544DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode, ExecUtmpMode);
53f47dfc
YW
5545
5546static const char* const exec_preserve_mode_table[_EXEC_PRESERVE_MODE_MAX] = {
5547 [EXEC_PRESERVE_NO] = "no",
5548 [EXEC_PRESERVE_YES] = "yes",
5549 [EXEC_PRESERVE_RESTART] = "restart",
5550};
5551
5552DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode, ExecPreserveMode, EXEC_PRESERVE_YES);
3536f49e 5553
6b7b2ed9 5554/* This table maps ExecDirectoryType to the setting it is configured with in the unit */
72fd1768 5555static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
3536f49e
YW
5556 [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
5557 [EXEC_DIRECTORY_STATE] = "StateDirectory",
5558 [EXEC_DIRECTORY_CACHE] = "CacheDirectory",
5559 [EXEC_DIRECTORY_LOGS] = "LogsDirectory",
5560 [EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
5561};
5562
5563DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);
b1edf445 5564
6b7b2ed9
LP
5565/* And this table maps ExecDirectoryType too, but to a generic term identifying the type of resource. This
5566 * one is supposed to be generic enough to be used for unit types that don't use ExecContext and per-unit
5567 * directories, specifically .timer units with their timestamp touch file. */
5568static const char* const exec_resource_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
5569 [EXEC_DIRECTORY_RUNTIME] = "runtime",
5570 [EXEC_DIRECTORY_STATE] = "state",
5571 [EXEC_DIRECTORY_CACHE] = "cache",
5572 [EXEC_DIRECTORY_LOGS] = "logs",
5573 [EXEC_DIRECTORY_CONFIGURATION] = "configuration",
5574};
5575
5576DEFINE_STRING_TABLE_LOOKUP(exec_resource_type, ExecDirectoryType);
5577
5578/* And this table also maps ExecDirectoryType, to the environment variable we pass the selected directory to
5579 * the service payload in. */
fb2042dd
YW
5580static const char* const exec_directory_env_name_table[_EXEC_DIRECTORY_TYPE_MAX] = {
5581 [EXEC_DIRECTORY_RUNTIME] = "RUNTIME_DIRECTORY",
5582 [EXEC_DIRECTORY_STATE] = "STATE_DIRECTORY",
5583 [EXEC_DIRECTORY_CACHE] = "CACHE_DIRECTORY",
5584 [EXEC_DIRECTORY_LOGS] = "LOGS_DIRECTORY",
5585 [EXEC_DIRECTORY_CONFIGURATION] = "CONFIGURATION_DIRECTORY",
5586};
5587
5588DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(exec_directory_env_name, ExecDirectoryType);
5589
b1edf445
LP
5590static const char* const exec_keyring_mode_table[_EXEC_KEYRING_MODE_MAX] = {
5591 [EXEC_KEYRING_INHERIT] = "inherit",
5592 [EXEC_KEYRING_PRIVATE] = "private",
5593 [EXEC_KEYRING_SHARED] = "shared",
5594};
5595
5596DEFINE_STRING_TABLE_LOOKUP(exec_keyring_mode, ExecKeyringMode);