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