]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/execute.c
core: fold property_get_input_fdname() and property_get_output_fdname() into one
[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 277static int open_null_as(int flags, int nfd) {
046a82c1 278 int fd;
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
046a82c1 286 return move_fd(fd, nfd, false);
071830ff
LP
287}
288
524daa8c 289static int connect_journal_socket(int fd, uid_t uid, gid_t gid) {
92a17af9 290 static const union sockaddr_union sa = {
b92bea5d
ZJS
291 .un.sun_family = AF_UNIX,
292 .un.sun_path = "/run/systemd/journal/stdout",
293 };
524daa8c
ZJS
294 uid_t olduid = UID_INVALID;
295 gid_t oldgid = GID_INVALID;
296 int r;
297
cad93f29 298 if (gid_is_valid(gid)) {
524daa8c
ZJS
299 oldgid = getgid();
300
92a17af9 301 if (setegid(gid) < 0)
524daa8c
ZJS
302 return -errno;
303 }
304
cad93f29 305 if (uid_is_valid(uid)) {
524daa8c
ZJS
306 olduid = getuid();
307
92a17af9 308 if (seteuid(uid) < 0) {
524daa8c
ZJS
309 r = -errno;
310 goto restore_gid;
311 }
312 }
313
92a17af9 314 r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0 ? -errno : 0;
524daa8c
ZJS
315
316 /* If we fail to restore the uid or gid, things will likely
317 fail later on. This should only happen if an LSM interferes. */
318
cad93f29 319 if (uid_is_valid(uid))
524daa8c
ZJS
320 (void) seteuid(olduid);
321
322 restore_gid:
cad93f29 323 if (gid_is_valid(gid))
524daa8c
ZJS
324 (void) setegid(oldgid);
325
326 return r;
327}
328
fd1f9c89 329static int connect_logger_as(
7a1ab780 330 Unit *unit,
fd1f9c89 331 const ExecContext *context,
af635cf3 332 const ExecParameters *params,
fd1f9c89
LP
333 ExecOutput output,
334 const char *ident,
fd1f9c89
LP
335 int nfd,
336 uid_t uid,
337 gid_t gid) {
338
524daa8c 339 int fd, r;
071830ff
LP
340
341 assert(context);
af635cf3 342 assert(params);
80876c20
LP
343 assert(output < _EXEC_OUTPUT_MAX);
344 assert(ident);
345 assert(nfd >= 0);
071830ff 346
54fe0cdb
LP
347 fd = socket(AF_UNIX, SOCK_STREAM, 0);
348 if (fd < 0)
80876c20 349 return -errno;
071830ff 350
524daa8c
ZJS
351 r = connect_journal_socket(fd, uid, gid);
352 if (r < 0)
353 return r;
071830ff 354
80876c20 355 if (shutdown(fd, SHUT_RD) < 0) {
03e334a1 356 safe_close(fd);
80876c20
LP
357 return -errno;
358 }
071830ff 359
fd1f9c89 360 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
531dca78 361
80876c20 362 dprintf(fd,
62bca2c6 363 "%s\n"
80876c20
LP
364 "%s\n"
365 "%i\n"
54fe0cdb
LP
366 "%i\n"
367 "%i\n"
368 "%i\n"
4f4a1dbf 369 "%i\n",
c867611e 370 context->syslog_identifier ?: ident,
af635cf3 371 params->flags & EXEC_PASS_LOG_UNIT ? unit->id : "",
54fe0cdb
LP
372 context->syslog_priority,
373 !!context->syslog_level_prefix,
aac8c0c3
LP
374 is_syslog_output(output),
375 is_kmsg_output(output),
3a1286b6 376 is_terminal_output(output));
80876c20 377
046a82c1 378 return move_fd(fd, nfd, false);
80876c20 379}
3a274a21 380static int open_terminal_as(const char *path, int flags, int nfd) {
046a82c1 381 int fd;
071830ff 382
80876c20
LP
383 assert(path);
384 assert(nfd >= 0);
071830ff 385
3a274a21 386 fd = open_terminal(path, flags | O_NOCTTY);
3cc2aff1 387 if (fd < 0)
80876c20 388 return fd;
071830ff 389
046a82c1 390 return move_fd(fd, nfd, false);
80876c20 391}
071830ff 392
08f3be7a
LP
393static int fixup_input(
394 const ExecContext *context,
395 int socket_fd,
396 bool apply_tty_stdin) {
397
398 ExecInput std_input;
399
400 assert(context);
401
402 std_input = context->std_input;
1e3ad081
LP
403
404 if (is_terminal_input(std_input) && !apply_tty_stdin)
405 return EXEC_INPUT_NULL;
071830ff 406
03fd9c49 407 if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
4f2d528d
LP
408 return EXEC_INPUT_NULL;
409
08f3be7a
LP
410 if (std_input == EXEC_INPUT_DATA && context->stdin_data_size == 0)
411 return EXEC_INPUT_NULL;
412
03fd9c49 413 return std_input;
4f2d528d
LP
414}
415
03fd9c49 416static int fixup_output(ExecOutput std_output, int socket_fd) {
4f2d528d 417
03fd9c49 418 if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
4f2d528d
LP
419 return EXEC_OUTPUT_INHERIT;
420
03fd9c49 421 return std_output;
4f2d528d
LP
422}
423
a34ceba6
LP
424static int setup_input(
425 const ExecContext *context,
426 const ExecParameters *params,
52c239d7
LB
427 int socket_fd,
428 int named_iofds[3]) {
a34ceba6 429
4f2d528d
LP
430 ExecInput i;
431
432 assert(context);
a34ceba6
LP
433 assert(params);
434
435 if (params->stdin_fd >= 0) {
436 if (dup2(params->stdin_fd, STDIN_FILENO) < 0)
437 return -errno;
438
439 /* Try to make this the controlling tty, if it is a tty, and reset it */
1fb0682e
LP
440 if (isatty(STDIN_FILENO)) {
441 (void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE);
442 (void) reset_terminal_fd(STDIN_FILENO, true);
443 }
a34ceba6
LP
444
445 return STDIN_FILENO;
446 }
4f2d528d 447
08f3be7a 448 i = fixup_input(context, socket_fd, params->flags & EXEC_APPLY_TTY_STDIN);
4f2d528d
LP
449
450 switch (i) {
071830ff 451
80876c20
LP
452 case EXEC_INPUT_NULL:
453 return open_null_as(O_RDONLY, STDIN_FILENO);
454
455 case EXEC_INPUT_TTY:
456 case EXEC_INPUT_TTY_FORCE:
457 case EXEC_INPUT_TTY_FAIL: {
046a82c1 458 int fd;
071830ff 459
1e22b5cd 460 fd = acquire_terminal(exec_context_tty_path(context),
970edce6
ZJS
461 i == EXEC_INPUT_TTY_FAIL,
462 i == EXEC_INPUT_TTY_FORCE,
463 false,
3a43da28 464 USEC_INFINITY);
970edce6 465 if (fd < 0)
80876c20
LP
466 return fd;
467
046a82c1 468 return move_fd(fd, STDIN_FILENO, false);
80876c20
LP
469 }
470
4f2d528d
LP
471 case EXEC_INPUT_SOCKET:
472 return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
473
52c239d7
LB
474 case EXEC_INPUT_NAMED_FD:
475 (void) fd_nonblock(named_iofds[STDIN_FILENO], false);
476 return dup2(named_iofds[STDIN_FILENO], STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
477
08f3be7a
LP
478 case EXEC_INPUT_DATA: {
479 int fd;
480
481 fd = acquire_data_fd(context->stdin_data, context->stdin_data_size, 0);
482 if (fd < 0)
483 return fd;
484
485 return move_fd(fd, STDIN_FILENO, false);
486 }
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
08f3be7a 532 i = fixup_input(context, 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
08f3be7a
LP
561 /* If the input is connected to anything that's not a /dev/null or a data fd, inherit that... */
562 if (!IN_SET(i, EXEC_INPUT_NULL, EXEC_INPUT_DATA))
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 ||
8cfa775f 1293 !hashmap_isempty(c->syscall_filter);
469830d1
LP
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
652bb263
YW
1708 if (context->n_bind_mounts > 0 ||
1709 !strv_isempty(context->directories[EXEC_DIRECTORY_RUNTIME].paths) ||
1710 !strv_isempty(context->directories[EXEC_DIRECTORY_STATE].paths) ||
1711 !strv_isempty(context->directories[EXEC_DIRECTORY_CACHE].paths) ||
1712 !strv_isempty(context->directories[EXEC_DIRECTORY_LOGS].paths) ||
1713 !strv_isempty(context->directories[EXEC_DIRECTORY_CONFIGURATION].paths))
d2d6c096
LP
1714 return true;
1715
8b44a3d2
LP
1716 if (context->mount_flags != 0)
1717 return true;
1718
1719 if (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir))
1720 return true;
1721
8b44a3d2
LP
1722 if (context->private_devices ||
1723 context->protect_system != PROTECT_SYSTEM_NO ||
59eeb84b
LP
1724 context->protect_home != PROTECT_HOME_NO ||
1725 context->protect_kernel_tunables ||
c575770b 1726 context->protect_kernel_modules ||
59eeb84b 1727 context->protect_control_groups)
8b44a3d2
LP
1728 return true;
1729
9c988f93 1730 if (context->mount_apivfs && (context->root_image || context->root_directory))
5d997827
LP
1731 return true;
1732
8b44a3d2
LP
1733 return false;
1734}
1735
d251207d
LP
1736static int setup_private_users(uid_t uid, gid_t gid) {
1737 _cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
1738 _cleanup_close_pair_ int errno_pipe[2] = { -1, -1 };
1739 _cleanup_close_ int unshare_ready_fd = -1;
1740 _cleanup_(sigkill_waitp) pid_t pid = 0;
1741 uint64_t c = 1;
1742 siginfo_t si;
1743 ssize_t n;
1744 int r;
1745
1746 /* Set up a user namespace and map root to root, the selected UID/GID to itself, and everything else to
1747 * nobody. In order to be able to write this mapping we need CAP_SETUID in the original user namespace, which
1748 * we however lack after opening the user namespace. To work around this we fork() a temporary child process,
1749 * which waits for the parent to create the new user namespace while staying in the original namespace. The
1750 * child then writes the UID mapping, under full privileges. The parent waits for the child to finish and
1751 * continues execution normally. */
1752
587ab01b
ZJS
1753 if (uid != 0 && uid_is_valid(uid)) {
1754 r = asprintf(&uid_map,
1755 "0 0 1\n" /* Map root → root */
1756 UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */
1757 uid, uid);
1758 if (r < 0)
1759 return -ENOMEM;
1760 } else {
e0f3720e 1761 uid_map = strdup("0 0 1\n"); /* The case where the above is the same */
587ab01b
ZJS
1762 if (!uid_map)
1763 return -ENOMEM;
1764 }
d251207d 1765
587ab01b
ZJS
1766 if (gid != 0 && gid_is_valid(gid)) {
1767 r = asprintf(&gid_map,
1768 "0 0 1\n" /* Map root → root */
1769 GID_FMT " " GID_FMT " 1\n", /* Map $GID → $GID */
1770 gid, gid);
1771 if (r < 0)
1772 return -ENOMEM;
1773 } else {
d251207d 1774 gid_map = strdup("0 0 1\n"); /* The case where the above is the same */
587ab01b
ZJS
1775 if (!gid_map)
1776 return -ENOMEM;
1777 }
d251207d
LP
1778
1779 /* Create a communication channel so that the parent can tell the child when it finished creating the user
1780 * namespace. */
1781 unshare_ready_fd = eventfd(0, EFD_CLOEXEC);
1782 if (unshare_ready_fd < 0)
1783 return -errno;
1784
1785 /* Create a communication channel so that the child can tell the parent a proper error code in case it
1786 * failed. */
1787 if (pipe2(errno_pipe, O_CLOEXEC) < 0)
1788 return -errno;
1789
1790 pid = fork();
1791 if (pid < 0)
1792 return -errno;
1793
1794 if (pid == 0) {
1795 _cleanup_close_ int fd = -1;
1796 const char *a;
1797 pid_t ppid;
1798
1799 /* Child process, running in the original user namespace. Let's update the parent's UID/GID map from
1800 * here, after the parent opened its own user namespace. */
1801
1802 ppid = getppid();
1803 errno_pipe[0] = safe_close(errno_pipe[0]);
1804
1805 /* Wait until the parent unshared the user namespace */
1806 if (read(unshare_ready_fd, &c, sizeof(c)) < 0) {
1807 r = -errno;
1808 goto child_fail;
1809 }
1810
1811 /* Disable the setgroups() system call in the child user namespace, for good. */
1812 a = procfs_file_alloca(ppid, "setgroups");
1813 fd = open(a, O_WRONLY|O_CLOEXEC);
1814 if (fd < 0) {
1815 if (errno != ENOENT) {
1816 r = -errno;
1817 goto child_fail;
1818 }
1819
1820 /* If the file is missing the kernel is too old, let's continue anyway. */
1821 } else {
1822 if (write(fd, "deny\n", 5) < 0) {
1823 r = -errno;
1824 goto child_fail;
1825 }
1826
1827 fd = safe_close(fd);
1828 }
1829
1830 /* First write the GID map */
1831 a = procfs_file_alloca(ppid, "gid_map");
1832 fd = open(a, O_WRONLY|O_CLOEXEC);
1833 if (fd < 0) {
1834 r = -errno;
1835 goto child_fail;
1836 }
1837 if (write(fd, gid_map, strlen(gid_map)) < 0) {
1838 r = -errno;
1839 goto child_fail;
1840 }
1841 fd = safe_close(fd);
1842
1843 /* The write the UID map */
1844 a = procfs_file_alloca(ppid, "uid_map");
1845 fd = open(a, O_WRONLY|O_CLOEXEC);
1846 if (fd < 0) {
1847 r = -errno;
1848 goto child_fail;
1849 }
1850 if (write(fd, uid_map, strlen(uid_map)) < 0) {
1851 r = -errno;
1852 goto child_fail;
1853 }
1854
1855 _exit(EXIT_SUCCESS);
1856
1857 child_fail:
1858 (void) write(errno_pipe[1], &r, sizeof(r));
1859 _exit(EXIT_FAILURE);
1860 }
1861
1862 errno_pipe[1] = safe_close(errno_pipe[1]);
1863
1864 if (unshare(CLONE_NEWUSER) < 0)
1865 return -errno;
1866
1867 /* Let the child know that the namespace is ready now */
1868 if (write(unshare_ready_fd, &c, sizeof(c)) < 0)
1869 return -errno;
1870
1871 /* Try to read an error code from the child */
1872 n = read(errno_pipe[0], &r, sizeof(r));
1873 if (n < 0)
1874 return -errno;
1875 if (n == sizeof(r)) { /* an error code was sent to us */
1876 if (r < 0)
1877 return r;
1878 return -EIO;
1879 }
1880 if (n != 0) /* on success we should have read 0 bytes */
1881 return -EIO;
1882
1883 r = wait_for_terminate(pid, &si);
1884 if (r < 0)
1885 return r;
1886 pid = 0;
1887
1888 /* If something strange happened with the child, let's consider this fatal, too */
1889 if (si.si_code != CLD_EXITED || si.si_status != 0)
1890 return -EIO;
1891
1892 return 0;
1893}
1894
3536f49e 1895static int setup_exec_directory(
07689d5d
LP
1896 const ExecContext *context,
1897 const ExecParameters *params,
1898 uid_t uid,
3536f49e 1899 gid_t gid,
3536f49e
YW
1900 ExecDirectoryType type,
1901 int *exit_status) {
07689d5d 1902
72fd1768 1903 static const int exit_status_table[_EXEC_DIRECTORY_TYPE_MAX] = {
3536f49e
YW
1904 [EXEC_DIRECTORY_RUNTIME] = EXIT_RUNTIME_DIRECTORY,
1905 [EXEC_DIRECTORY_STATE] = EXIT_STATE_DIRECTORY,
1906 [EXEC_DIRECTORY_CACHE] = EXIT_CACHE_DIRECTORY,
1907 [EXEC_DIRECTORY_LOGS] = EXIT_LOGS_DIRECTORY,
1908 [EXEC_DIRECTORY_CONFIGURATION] = EXIT_CONFIGURATION_DIRECTORY,
1909 };
07689d5d
LP
1910 char **rt;
1911 int r;
1912
1913 assert(context);
1914 assert(params);
72fd1768 1915 assert(type >= 0 && type < _EXEC_DIRECTORY_TYPE_MAX);
3536f49e 1916 assert(exit_status);
07689d5d 1917
3536f49e
YW
1918 if (!params->prefix[type])
1919 return 0;
1920
8679efde 1921 if (params->flags & EXEC_CHOWN_DIRECTORIES) {
3536f49e
YW
1922 if (!uid_is_valid(uid))
1923 uid = 0;
1924 if (!gid_is_valid(gid))
1925 gid = 0;
1926 }
1927
1928 STRV_FOREACH(rt, context->directories[type].paths) {
6c47cd7d
LP
1929 _cleanup_free_ char *p = NULL, *pp = NULL;
1930 const char *effective;
07689d5d 1931
3536f49e
YW
1932 p = strjoin(params->prefix[type], "/", *rt);
1933 if (!p) {
1934 r = -ENOMEM;
1935 goto fail;
1936 }
07689d5d 1937
23a7448e
YW
1938 r = mkdir_parents_label(p, 0755);
1939 if (r < 0)
3536f49e 1940 goto fail;
23a7448e 1941
8092a48c
YW
1942 if (context->dynamic_user &&
1943 !IN_SET(type, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION)) {
6c47cd7d
LP
1944 _cleanup_free_ char *private_root = NULL, *relative = NULL, *parent = NULL;
1945
1946 /* So, here's one extra complication when dealing with DynamicUser=1 units. In that case we
1947 * want to avoid leaving a directory around fully accessible that is owned by a dynamic user
1948 * whose UID is later on reused. To lock this down we use the same trick used by container
1949 * managers to prohibit host users to get access to files of the same UID in containers: we
1950 * place everything inside a directory that has an access mode of 0700 and is owned root:root,
1951 * so that it acts as security boundary for unprivileged host code. We then use fs namespacing
1952 * to make this directory permeable for the service itself.
1953 *
1954 * Specifically: for a service which wants a special directory "foo/" we first create a
1955 * directory "private/" with access mode 0700 owned by root:root. Then we place "foo" inside of
1956 * that directory (i.e. "private/foo/"), and make "foo" a symlink to "private/foo". This way,
1957 * privileged host users can access "foo/" as usual, but unprivileged host users can't look
1958 * into it. Inside of the namespaceof the container "private/" is replaced by a more liberally
1959 * accessible tmpfs, into which the host's "private/foo/" is mounted under the same name, thus
1960 * disabling the access boundary for the service and making sure it only gets access to the
1961 * dirs it needs but no others. Tricky? Yes, absolutely, but it works!
1962 *
1963 * Note that we don't do this for EXEC_DIRECTORY_CONFIGURATION as that's assumed not to be
8092a48c
YW
1964 * owned by the service itself.
1965 * Also, note that we don't do this for EXEC_DIRECTORY_RUNTIME as that's often used for sharing
1966 * files or sockets with other services. */
6c47cd7d
LP
1967
1968 private_root = strjoin(params->prefix[type], "/private");
1969 if (!private_root) {
1970 r = -ENOMEM;
1971 goto fail;
1972 }
1973
1974 /* First set up private root if it doesn't exist yet, with access mode 0700 and owned by root:root */
c31ad024 1975 r = mkdir_safe_label(private_root, 0700, 0, 0, false);
6c47cd7d
LP
1976 if (r < 0)
1977 goto fail;
1978
1979 pp = strjoin(private_root, "/", *rt);
1980 if (!pp) {
1981 r = -ENOMEM;
1982 goto fail;
1983 }
1984
1985 /* Create all directories between the configured directory and this private root, and mark them 0755 */
1986 r = mkdir_parents_label(pp, 0755);
1987 if (r < 0)
1988 goto fail;
1989
1990 /* Finally, create the actual directory for the service */
1991 r = mkdir_label(pp, context->directories[type].mode);
1992 if (r < 0 && r != -EEXIST)
1993 goto fail;
1994
1995 parent = dirname_malloc(p);
1996 if (!parent) {
1997 r = -ENOMEM;
1998 goto fail;
1999 }
2000
2001 r = path_make_relative(parent, pp, &relative);
2002 if (r < 0)
2003 goto fail;
2004
2005 /* And link it up from the original place */
2006 r = symlink_idempotent(relative, p);
2007 if (r < 0)
2008 goto fail;
2009
2010 effective = pp;
2011
2012 } else {
2013 r = mkdir_label(p, context->directories[type].mode);
2014 if (r < 0 && r != -EEXIST)
2015 goto fail;
2016
2017 effective = p;
2018 }
a1164ae3
LP
2019
2020 /* First lock down the access mode */
6c47cd7d 2021 if (chmod(effective, context->directories[type].mode) < 0) {
a1164ae3 2022 r = -errno;
3536f49e 2023 goto fail;
a1164ae3 2024 }
07689d5d 2025
c71b2eb7
LP
2026 /* Don't change the owner of the configuration directory, as in the common case it is not written to by
2027 * a service, and shall not be writable. */
2028 if (type == EXEC_DIRECTORY_CONFIGURATION)
2029 continue;
2030
a1164ae3 2031 /* Then, change the ownership of the whole tree, if necessary */
6c47cd7d 2032 r = path_chown_recursive(effective, uid, gid);
07689d5d 2033 if (r < 0)
3536f49e 2034 goto fail;
07689d5d
LP
2035 }
2036
2037 return 0;
3536f49e
YW
2038
2039fail:
2040 *exit_status = exit_status_table[type];
3536f49e 2041 return r;
07689d5d
LP
2042}
2043
cefc33ae
LP
2044static int setup_smack(
2045 const ExecContext *context,
2046 const ExecCommand *command) {
2047
cefc33ae
LP
2048 int r;
2049
2050 assert(context);
2051 assert(command);
2052
cefc33ae
LP
2053 if (context->smack_process_label) {
2054 r = mac_smack_apply_pid(0, context->smack_process_label);
2055 if (r < 0)
2056 return r;
2057 }
2058#ifdef SMACK_DEFAULT_PROCESS_LABEL
2059 else {
2060 _cleanup_free_ char *exec_label = NULL;
2061
2062 r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label);
4c701096 2063 if (r < 0 && !IN_SET(r, -ENODATA, -EOPNOTSUPP))
cefc33ae
LP
2064 return r;
2065
2066 r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL);
2067 if (r < 0)
2068 return r;
2069 }
cefc33ae
LP
2070#endif
2071
2072 return 0;
2073}
2074
6c47cd7d
LP
2075static int compile_bind_mounts(
2076 const ExecContext *context,
2077 const ExecParameters *params,
2078 BindMount **ret_bind_mounts,
2079 unsigned *ret_n_bind_mounts,
2080 char ***ret_empty_directories) {
2081
2082 _cleanup_strv_free_ char **empty_directories = NULL;
2083 BindMount *bind_mounts;
2084 unsigned n, h = 0, i;
2085 ExecDirectoryType t;
2086 int r;
2087
2088 assert(context);
2089 assert(params);
2090 assert(ret_bind_mounts);
2091 assert(ret_n_bind_mounts);
2092 assert(ret_empty_directories);
2093
2094 n = context->n_bind_mounts;
2095 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
2096 if (!params->prefix[t])
2097 continue;
2098
2099 n += strv_length(context->directories[t].paths);
2100 }
2101
2102 if (n <= 0) {
2103 *ret_bind_mounts = NULL;
2104 *ret_n_bind_mounts = 0;
2105 *ret_empty_directories = NULL;
2106 return 0;
2107 }
2108
2109 bind_mounts = new(BindMount, n);
2110 if (!bind_mounts)
2111 return -ENOMEM;
2112
a8cabc61 2113 for (i = 0; i < context->n_bind_mounts; i++) {
6c47cd7d
LP
2114 BindMount *item = context->bind_mounts + i;
2115 char *s, *d;
2116
2117 s = strdup(item->source);
2118 if (!s) {
2119 r = -ENOMEM;
2120 goto finish;
2121 }
2122
2123 d = strdup(item->destination);
2124 if (!d) {
2125 free(s);
2126 r = -ENOMEM;
2127 goto finish;
2128 }
2129
2130 bind_mounts[h++] = (BindMount) {
2131 .source = s,
2132 .destination = d,
2133 .read_only = item->read_only,
2134 .recursive = item->recursive,
2135 .ignore_enoent = item->ignore_enoent,
2136 };
2137 }
2138
2139 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
2140 char **suffix;
2141
2142 if (!params->prefix[t])
2143 continue;
2144
2145 if (strv_isempty(context->directories[t].paths))
2146 continue;
2147
8092a48c
YW
2148 if (context->dynamic_user &&
2149 !IN_SET(t, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION)) {
6c47cd7d
LP
2150 char *private_root;
2151
2152 /* So this is for a dynamic user, and we need to make sure the process can access its own
2153 * directory. For that we overmount the usually inaccessible "private" subdirectory with a
2154 * tmpfs that makes it accessible and is empty except for the submounts we do this for. */
2155
2156 private_root = strjoin(params->prefix[t], "/private");
2157 if (!private_root) {
2158 r = -ENOMEM;
2159 goto finish;
2160 }
2161
2162 r = strv_consume(&empty_directories, private_root);
2163 if (r < 0) {
2164 r = -ENOMEM;
2165 goto finish;
2166 }
2167 }
2168
2169 STRV_FOREACH(suffix, context->directories[t].paths) {
2170 char *s, *d;
2171
8092a48c
YW
2172 if (context->dynamic_user &&
2173 !IN_SET(t, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION))
6c47cd7d
LP
2174 s = strjoin(params->prefix[t], "/private/", *suffix);
2175 else
2176 s = strjoin(params->prefix[t], "/", *suffix);
2177 if (!s) {
2178 r = -ENOMEM;
2179 goto finish;
2180 }
2181
2182 d = strdup(s);
2183 if (!d) {
2184 free(s);
2185 r = -ENOMEM;
2186 goto finish;
2187 }
2188
2189 bind_mounts[h++] = (BindMount) {
2190 .source = s,
2191 .destination = d,
2192 .read_only = false,
2193 .recursive = true,
2194 .ignore_enoent = false,
2195 };
2196 }
2197 }
2198
2199 assert(h == n);
2200
2201 *ret_bind_mounts = bind_mounts;
2202 *ret_n_bind_mounts = n;
2203 *ret_empty_directories = empty_directories;
2204
2205 empty_directories = NULL;
2206
2207 return (int) n;
2208
2209finish:
2210 bind_mount_free_many(bind_mounts, h);
2211 return r;
2212}
2213
6818c54c
LP
2214static int apply_mount_namespace(
2215 Unit *u,
2216 ExecCommand *command,
2217 const ExecContext *context,
2218 const ExecParameters *params,
2219 ExecRuntime *runtime) {
2220
7bcef4ef 2221 _cleanup_strv_free_ char **empty_directories = NULL;
93c6bb51 2222 char *tmp = NULL, *var = NULL;
915e6d16 2223 const char *root_dir = NULL, *root_image = NULL;
bb0ff3fb 2224 NamespaceInfo ns_info = {
af964954 2225 .ignore_protect_paths = false,
93c6bb51
DH
2226 .private_dev = context->private_devices,
2227 .protect_control_groups = context->protect_control_groups,
2228 .protect_kernel_tunables = context->protect_kernel_tunables,
2229 .protect_kernel_modules = context->protect_kernel_modules,
5d997827 2230 .mount_apivfs = context->mount_apivfs,
93c6bb51 2231 };
165a31c0 2232 bool needs_sandboxing;
6c47cd7d
LP
2233 BindMount *bind_mounts = NULL;
2234 unsigned n_bind_mounts = 0;
6818c54c 2235 int r;
93c6bb51 2236
2b3c1b9e
DH
2237 assert(context);
2238
93c6bb51
DH
2239 /* The runtime struct only contains the parent of the private /tmp,
2240 * which is non-accessible to world users. Inside of it there's a /tmp
2241 * that is sticky, and that's the one we want to use here. */
2242
2243 if (context->private_tmp && runtime) {
2244 if (runtime->tmp_dir)
2245 tmp = strjoina(runtime->tmp_dir, "/tmp");
2246 if (runtime->var_tmp_dir)
2247 var = strjoina(runtime->var_tmp_dir, "/tmp");
2248 }
2249
915e6d16
LP
2250 if (params->flags & EXEC_APPLY_CHROOT) {
2251 root_image = context->root_image;
2252
2253 if (!root_image)
2254 root_dir = context->root_directory;
2255 }
93c6bb51 2256
6c47cd7d
LP
2257 r = compile_bind_mounts(context, params, &bind_mounts, &n_bind_mounts, &empty_directories);
2258 if (r < 0)
2259 return r;
2260
af964954
DH
2261 /*
2262 * If DynamicUser=no and RootDirectory= is set then lets pass a relaxed
2263 * sandbox info, otherwise enforce it, don't ignore protected paths and
2264 * fail if we are enable to apply the sandbox inside the mount namespace.
2265 */
2266 if (!context->dynamic_user && root_dir)
2267 ns_info.ignore_protect_paths = true;
2268
165a31c0 2269 needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & EXEC_COMMAND_FULLY_PRIVILEGED);
6818c54c 2270
915e6d16 2271 r = setup_namespace(root_dir, root_image,
7bcef4ef 2272 &ns_info, context->read_write_paths,
165a31c0
LP
2273 needs_sandboxing ? context->read_only_paths : NULL,
2274 needs_sandboxing ? context->inaccessible_paths : NULL,
6c47cd7d
LP
2275 empty_directories,
2276 bind_mounts,
2277 n_bind_mounts,
93c6bb51
DH
2278 tmp,
2279 var,
165a31c0
LP
2280 needs_sandboxing ? context->protect_home : PROTECT_HOME_NO,
2281 needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO,
915e6d16
LP
2282 context->mount_flags,
2283 DISSECT_IMAGE_DISCARD_ON_LOOP);
93c6bb51 2284
6c47cd7d
LP
2285 bind_mount_free_many(bind_mounts, n_bind_mounts);
2286
93c6bb51
DH
2287 /* If we couldn't set up the namespace this is probably due to a
2288 * missing capability. In this case, silently proceeed. */
2289 if (IN_SET(r, -EPERM, -EACCES)) {
93c6bb51 2290 log_unit_debug_errno(u, r, "Failed to set up namespace, assuming containerized execution, ignoring: %m");
86ffb325 2291 return 0;
93c6bb51
DH
2292 }
2293
2294 return r;
2295}
2296
915e6d16
LP
2297static int apply_working_directory(
2298 const ExecContext *context,
2299 const ExecParameters *params,
2300 const char *home,
376fecf6
LP
2301 const bool needs_mount_ns,
2302 int *exit_status) {
915e6d16 2303
6732edab 2304 const char *d, *wd;
2b3c1b9e
DH
2305
2306 assert(context);
376fecf6 2307 assert(exit_status);
2b3c1b9e 2308
6732edab
LP
2309 if (context->working_directory_home) {
2310
376fecf6
LP
2311 if (!home) {
2312 *exit_status = EXIT_CHDIR;
6732edab 2313 return -ENXIO;
376fecf6 2314 }
6732edab 2315
2b3c1b9e 2316 wd = home;
6732edab
LP
2317
2318 } else if (context->working_directory)
2b3c1b9e
DH
2319 wd = context->working_directory;
2320 else
2321 wd = "/";
e7f1e7c6
DH
2322
2323 if (params->flags & EXEC_APPLY_CHROOT) {
2324 if (!needs_mount_ns && context->root_directory)
376fecf6
LP
2325 if (chroot(context->root_directory) < 0) {
2326 *exit_status = EXIT_CHROOT;
e7f1e7c6 2327 return -errno;
376fecf6 2328 }
e7f1e7c6 2329
2b3c1b9e
DH
2330 d = wd;
2331 } else
3b0e5bb5 2332 d = prefix_roota(context->root_directory, wd);
e7f1e7c6 2333
376fecf6
LP
2334 if (chdir(d) < 0 && !context->working_directory_missing_ok) {
2335 *exit_status = EXIT_CHDIR;
2b3c1b9e 2336 return -errno;
376fecf6 2337 }
e7f1e7c6
DH
2338
2339 return 0;
2340}
2341
b1edf445
LP
2342static int setup_keyring(
2343 Unit *u,
2344 const ExecContext *context,
2345 const ExecParameters *p,
2346 uid_t uid, gid_t gid) {
2347
74dd6b51 2348 key_serial_t keyring;
b1edf445 2349 int r;
74dd6b51
LP
2350
2351 assert(u);
b1edf445 2352 assert(context);
74dd6b51
LP
2353 assert(p);
2354
2355 /* Let's set up a new per-service "session" kernel keyring for each system service. This has the benefit that
2356 * each service runs with its own keyring shared among all processes of the service, but with no hook-up beyond
2357 * that scope, and in particular no link to the per-UID keyring. If we don't do this the keyring will be
2358 * automatically created on-demand and then linked to the per-UID keyring, by the kernel. The kernel's built-in
2359 * on-demand behaviour is very appropriate for login users, but probably not so much for system services, where
2360 * UIDs are not necessarily specific to a service but reused (at least in the case of UID 0). */
2361
2362 if (!(p->flags & EXEC_NEW_KEYRING))
2363 return 0;
2364
b1edf445
LP
2365 if (context->keyring_mode == EXEC_KEYRING_INHERIT)
2366 return 0;
2367
74dd6b51
LP
2368 keyring = keyctl(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
2369 if (keyring == -1) {
2370 if (errno == ENOSYS)
8002fb97 2371 log_unit_debug_errno(u, errno, "Kernel keyring not supported, ignoring.");
74dd6b51 2372 else if (IN_SET(errno, EACCES, EPERM))
8002fb97 2373 log_unit_debug_errno(u, errno, "Kernel keyring access prohibited, ignoring.");
74dd6b51 2374 else if (errno == EDQUOT)
8002fb97 2375 log_unit_debug_errno(u, errno, "Out of kernel keyrings to allocate, ignoring.");
74dd6b51 2376 else
8002fb97 2377 return log_unit_error_errno(u, errno, "Setting up kernel keyring failed: %m");
74dd6b51
LP
2378
2379 return 0;
2380 }
2381
b3415f5d
LP
2382 /* Populate they keyring with the invocation ID by default. */
2383 if (!sd_id128_is_null(u->invocation_id)) {
2384 key_serial_t key;
2385
2386 key = add_key("user", "invocation_id", &u->invocation_id, sizeof(u->invocation_id), KEY_SPEC_SESSION_KEYRING);
2387 if (key == -1)
8002fb97 2388 log_unit_debug_errno(u, errno, "Failed to add invocation ID to keyring, ignoring: %m");
b3415f5d
LP
2389 else {
2390 if (keyctl(KEYCTL_SETPERM, key,
2391 KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH|
2392 KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH, 0, 0) < 0)
8002fb97 2393 return log_unit_error_errno(u, errno, "Failed to restrict invocation ID permission: %m");
b3415f5d
LP
2394 }
2395 }
2396
74dd6b51
LP
2397 /* And now, make the keyring owned by the service's user */
2398 if (uid_is_valid(uid) || gid_is_valid(gid))
2399 if (keyctl(KEYCTL_CHOWN, keyring, uid, gid, 0) < 0)
8002fb97 2400 return log_unit_error_errno(u, errno, "Failed to change ownership of session keyring: %m");
74dd6b51 2401
b1edf445
LP
2402 /* When requested link the user keyring into the session keyring. */
2403 if (context->keyring_mode == EXEC_KEYRING_SHARED) {
2404 uid_t saved_uid;
2405 gid_t saved_gid;
2406
2407 /* Acquiring a reference to the user keyring is nasty. We briefly change identity in order to get things
2408 * set up properly by the kernel. If we don't do that then we can't create it atomically, and that
2409 * sucks for parallel execution. This mimics what pam_keyinit does, too.*/
2410
2411 saved_uid = getuid();
2412 saved_gid = getgid();
2413
2414 if (gid_is_valid(gid) && gid != saved_gid) {
2415 if (setregid(gid, -1) < 0)
8002fb97 2416 return log_unit_error_errno(u, errno, "Failed to change GID for user keyring: %m");
b1edf445
LP
2417 }
2418
2419 if (uid_is_valid(uid) && uid != saved_uid) {
2420 if (setreuid(uid, -1) < 0) {
2421 (void) setregid(saved_gid, -1);
8002fb97 2422 return log_unit_error_errno(u, errno, "Failed to change UID for user keyring: %m");
b1edf445
LP
2423 }
2424 }
2425
2426 if (keyctl(KEYCTL_LINK,
2427 KEY_SPEC_USER_KEYRING,
2428 KEY_SPEC_SESSION_KEYRING, 0, 0) < 0) {
2429
2430 r = -errno;
2431
2432 (void) setreuid(saved_uid, -1);
2433 (void) setregid(saved_gid, -1);
2434
8002fb97 2435 return log_unit_error_errno(u, r, "Failed to link user keyring into session keyring: %m");
b1edf445
LP
2436 }
2437
2438 if (uid_is_valid(uid) && uid != saved_uid) {
2439 if (setreuid(saved_uid, -1) < 0) {
2440 (void) setregid(saved_gid, -1);
8002fb97 2441 return log_unit_error_errno(u, errno, "Failed to change UID back for user keyring: %m");
b1edf445
LP
2442 }
2443 }
2444
2445 if (gid_is_valid(gid) && gid != saved_gid) {
2446 if (setregid(saved_gid, -1) < 0)
8002fb97 2447 return log_unit_error_errno(u, errno, "Failed to change GID back for user keyring: %m");
b1edf445 2448 }
61ceaea5 2449 }
b1edf445 2450
74dd6b51
LP
2451 return 0;
2452}
2453
29206d46
LP
2454static void append_socket_pair(int *array, unsigned *n, int pair[2]) {
2455 assert(array);
2456 assert(n);
2457
2458 if (!pair)
2459 return;
2460
2461 if (pair[0] >= 0)
2462 array[(*n)++] = pair[0];
2463 if (pair[1] >= 0)
2464 array[(*n)++] = pair[1];
2465}
2466
a34ceba6
LP
2467static int close_remaining_fds(
2468 const ExecParameters *params,
2469 ExecRuntime *runtime,
29206d46 2470 DynamicCreds *dcreds,
00d9ef85 2471 int user_lookup_fd,
a34ceba6
LP
2472 int socket_fd,
2473 int *fds, unsigned n_fds) {
2474
2475 unsigned n_dont_close = 0;
00d9ef85 2476 int dont_close[n_fds + 12];
a34ceba6
LP
2477
2478 assert(params);
2479
2480 if (params->stdin_fd >= 0)
2481 dont_close[n_dont_close++] = params->stdin_fd;
2482 if (params->stdout_fd >= 0)
2483 dont_close[n_dont_close++] = params->stdout_fd;
2484 if (params->stderr_fd >= 0)
2485 dont_close[n_dont_close++] = params->stderr_fd;
2486
2487 if (socket_fd >= 0)
2488 dont_close[n_dont_close++] = socket_fd;
2489 if (n_fds > 0) {
2490 memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
2491 n_dont_close += n_fds;
2492 }
2493
29206d46
LP
2494 if (runtime)
2495 append_socket_pair(dont_close, &n_dont_close, runtime->netns_storage_socket);
2496
2497 if (dcreds) {
2498 if (dcreds->user)
2499 append_socket_pair(dont_close, &n_dont_close, dcreds->user->storage_socket);
2500 if (dcreds->group)
2501 append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket);
a34ceba6
LP
2502 }
2503
00d9ef85
LP
2504 if (user_lookup_fd >= 0)
2505 dont_close[n_dont_close++] = user_lookup_fd;
2506
a34ceba6
LP
2507 return close_all_fds(dont_close, n_dont_close);
2508}
2509
00d9ef85
LP
2510static int send_user_lookup(
2511 Unit *unit,
2512 int user_lookup_fd,
2513 uid_t uid,
2514 gid_t gid) {
2515
2516 assert(unit);
2517
2518 /* Send the resolved UID/GID to PID 1 after we learnt it. We send a single datagram, containing the UID/GID
2519 * data as well as the unit name. Note that we suppress sending this if no user/group to resolve was
2520 * specified. */
2521
2522 if (user_lookup_fd < 0)
2523 return 0;
2524
2525 if (!uid_is_valid(uid) && !gid_is_valid(gid))
2526 return 0;
2527
2528 if (writev(user_lookup_fd,
2529 (struct iovec[]) {
e6a7ec4b
LP
2530 IOVEC_INIT(&uid, sizeof(uid)),
2531 IOVEC_INIT(&gid, sizeof(gid)),
2532 IOVEC_INIT_STRING(unit->id) }, 3) < 0)
00d9ef85
LP
2533 return -errno;
2534
2535 return 0;
2536}
2537
6732edab
LP
2538static int acquire_home(const ExecContext *c, uid_t uid, const char** home, char **buf) {
2539 int r;
2540
2541 assert(c);
2542 assert(home);
2543 assert(buf);
2544
2545 /* If WorkingDirectory=~ is set, try to acquire a usable home directory. */
2546
2547 if (*home)
2548 return 0;
2549
2550 if (!c->working_directory_home)
2551 return 0;
2552
2553 if (uid == 0) {
2554 /* Hardcode /root as home directory for UID 0 */
2555 *home = "/root";
2556 return 1;
2557 }
2558
2559 r = get_home_dir(buf);
2560 if (r < 0)
2561 return r;
2562
2563 *home = *buf;
2564 return 1;
2565}
2566
da50b85a
LP
2567static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p, char ***ret) {
2568 _cleanup_strv_free_ char ** list = NULL;
2569 ExecDirectoryType t;
2570 int r;
2571
2572 assert(c);
2573 assert(p);
2574 assert(ret);
2575
2576 assert(c->dynamic_user);
2577
2578 /* Compile a list of paths that it might make sense to read the owning UID from to use as initial candidate for
2579 * dynamic UID allocation, in order to save us from doing costly recursive chown()s of the special
2580 * directories. */
2581
2582 for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
2583 char **i;
2584
2585 if (t == EXEC_DIRECTORY_CONFIGURATION)
2586 continue;
2587
2588 if (!p->prefix[t])
2589 continue;
2590
2591 STRV_FOREACH(i, c->directories[t].paths) {
2592 char *e;
2593
8092a48c
YW
2594 if (t == EXEC_DIRECTORY_RUNTIME)
2595 e = strjoin(p->prefix[t], "/", *i);
2596 else
2597 e = strjoin(p->prefix[t], "/private/", *i);
da50b85a
LP
2598 if (!e)
2599 return -ENOMEM;
2600
2601 r = strv_consume(&list, e);
2602 if (r < 0)
2603 return r;
2604 }
2605 }
2606
2607 *ret = list;
2608 list = NULL;
2609
2610 return 0;
2611}
2612
ff0af2a1 2613static int exec_child(
f2341e0a 2614 Unit *unit,
ff0af2a1
LP
2615 ExecCommand *command,
2616 const ExecContext *context,
2617 const ExecParameters *params,
2618 ExecRuntime *runtime,
29206d46 2619 DynamicCreds *dcreds,
ff0af2a1
LP
2620 char **argv,
2621 int socket_fd,
52c239d7 2622 int named_iofds[3],
4c47affc
FB
2623 int *fds,
2624 unsigned n_storage_fds,
9b141911 2625 unsigned n_socket_fds,
ff0af2a1 2626 char **files_env,
00d9ef85 2627 int user_lookup_fd,
12145637 2628 int *exit_status) {
d35fbf6b 2629
2065ca69 2630 _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **final_argv = NULL;
6732edab 2631 _cleanup_free_ char *mac_selinux_context_net = NULL, *home_buffer = NULL;
4d885bd3
DH
2632 _cleanup_free_ gid_t *supplementary_gids = NULL;
2633 const char *username = NULL, *groupname = NULL;
2b3c1b9e 2634 const char *home = NULL, *shell = NULL;
7bce046b
LP
2635 dev_t journal_stream_dev = 0;
2636 ino_t journal_stream_ino = 0;
165a31c0
LP
2637 bool needs_sandboxing, /* Do we need to set up full sandboxing? (i.e. all namespacing, all MAC stuff, caps, yadda yadda */
2638 needs_setuid, /* Do we need to do the actual setresuid()/setresgid() calls? */
2639 needs_mount_namespace, /* Do we need to set up a mount namespace for this kernel? */
2640 needs_ambient_hack; /* Do we need to apply the ambient capabilities hack? */
349cc4a5 2641#if HAVE_SELINUX
43b1f709 2642 bool use_selinux = false;
ecfbc84f 2643#endif
f9fa32f0 2644#if ENABLE_SMACK
43b1f709 2645 bool use_smack = false;
ecfbc84f 2646#endif
349cc4a5 2647#if HAVE_APPARMOR
43b1f709 2648 bool use_apparmor = false;
ecfbc84f 2649#endif
fed1e721
LP
2650 uid_t uid = UID_INVALID;
2651 gid_t gid = GID_INVALID;
4d885bd3 2652 int i, r, ngids = 0;
4c47affc 2653 unsigned n_fds;
3536f49e 2654 ExecDirectoryType dt;
165a31c0 2655 int secure_bits;
034c6ed7 2656
f2341e0a 2657 assert(unit);
5cb5a6ff
LP
2658 assert(command);
2659 assert(context);
d35fbf6b 2660 assert(params);
ff0af2a1 2661 assert(exit_status);
d35fbf6b
DM
2662
2663 rename_process_from_path(command->path);
2664
2665 /* We reset exactly these signals, since they are the
2666 * only ones we set to SIG_IGN in the main daemon. All
2667 * others we leave untouched because we set them to
2668 * SIG_DFL or a valid handler initially, both of which
2669 * will be demoted to SIG_DFL. */
ce30c8dc
LP
2670 (void) default_signals(SIGNALS_CRASH_HANDLER,
2671 SIGNALS_IGNORE, -1);
d35fbf6b
DM
2672
2673 if (context->ignore_sigpipe)
ce30c8dc 2674 (void) ignore_signals(SIGPIPE, -1);
d35fbf6b 2675
ff0af2a1
LP
2676 r = reset_signal_mask();
2677 if (r < 0) {
2678 *exit_status = EXIT_SIGNAL_MASK;
12145637 2679 return log_unit_error_errno(unit, r, "Failed to set process signal mask: %m");
d35fbf6b 2680 }
034c6ed7 2681
d35fbf6b
DM
2682 if (params->idle_pipe)
2683 do_idle_pipe_dance(params->idle_pipe);
4f2d528d 2684
2c027c62
LP
2685 /* Close fds we don't need very early to make sure we don't block init reexecution because it cannot bind its
2686 * sockets. Among the fds we close are the logging fds, and we want to keep them closed, so that we don't have
2687 * any fds open we don't really want open during the transition. In order to make logging work, we switch the
2688 * log subsystem into open_when_needed mode, so that it reopens the logs on every single log call. */
ff0af2a1 2689
d35fbf6b 2690 log_forget_fds();
2c027c62 2691 log_set_open_when_needed(true);
4f2d528d 2692
40a80078
LP
2693 /* In case anything used libc syslog(), close this here, too */
2694 closelog();
2695
4c47affc 2696 n_fds = n_storage_fds + n_socket_fds;
00d9ef85 2697 r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, fds, n_fds);
ff0af2a1
LP
2698 if (r < 0) {
2699 *exit_status = EXIT_FDS;
12145637 2700 return log_unit_error_errno(unit, r, "Failed to close unwanted file descriptors: %m");
8c7be95e
LP
2701 }
2702
d35fbf6b
DM
2703 if (!context->same_pgrp)
2704 if (setsid() < 0) {
ff0af2a1 2705 *exit_status = EXIT_SETSID;
12145637 2706 return log_unit_error_errno(unit, errno, "Failed to create new process session: %m");
d35fbf6b 2707 }
9e2f7c11 2708
1e22b5cd 2709 exec_context_tty_reset(context, params);
d35fbf6b 2710
c891efaf 2711 if (unit_shall_confirm_spawn(unit)) {
7d5ceb64 2712 const char *vc = params->confirm_spawn;
3b20f877
FB
2713 _cleanup_free_ char *cmdline = NULL;
2714
2715 cmdline = exec_command_line(argv);
2716 if (!cmdline) {
0460aa5c 2717 *exit_status = EXIT_MEMORY;
12145637 2718 return log_oom();
3b20f877 2719 }
d35fbf6b 2720
eedf223a 2721 r = ask_for_confirmation(vc, unit, cmdline);
3b20f877
FB
2722 if (r != CONFIRM_EXECUTE) {
2723 if (r == CONFIRM_PRETEND_SUCCESS) {
2724 *exit_status = EXIT_SUCCESS;
2725 return 0;
2726 }
ff0af2a1 2727 *exit_status = EXIT_CONFIRM;
12145637 2728 log_unit_error(unit, "Execution cancelled by the user");
d35fbf6b 2729 return -ECANCELED;
d35fbf6b
DM
2730 }
2731 }
1a63a750 2732
29206d46 2733 if (context->dynamic_user && dcreds) {
da50b85a 2734 _cleanup_strv_free_ char **suggested_paths = NULL;
29206d46 2735
409093fe
LP
2736 /* Make sure we bypass our own NSS module for any NSS checks */
2737 if (putenv((char*) "SYSTEMD_NSS_DYNAMIC_BYPASS=1") != 0) {
2738 *exit_status = EXIT_USER;
12145637 2739 return log_unit_error_errno(unit, errno, "Failed to update environment: %m");
409093fe
LP
2740 }
2741
da50b85a
LP
2742 r = compile_suggested_paths(context, params, &suggested_paths);
2743 if (r < 0) {
2744 *exit_status = EXIT_MEMORY;
2745 return log_oom();
2746 }
2747
2748 r = dynamic_creds_realize(dcreds, suggested_paths, &uid, &gid);
ff0af2a1
LP
2749 if (r < 0) {
2750 *exit_status = EXIT_USER;
e2b0cc34
YW
2751 if (r == -EILSEQ) {
2752 log_unit_error(unit, "Failed to update dynamic user credentials: User or group with specified name already exists.");
2753 return -EOPNOTSUPP;
2754 }
12145637 2755 return log_unit_error_errno(unit, r, "Failed to update dynamic user credentials: %m");
524daa8c 2756 }
524daa8c 2757
70dd455c 2758 if (!uid_is_valid(uid)) {
29206d46 2759 *exit_status = EXIT_USER;
12145637 2760 log_unit_error(unit, "UID validation failed for \""UID_FMT"\"", uid);
70dd455c
ZJS
2761 return -ESRCH;
2762 }
2763
2764 if (!gid_is_valid(gid)) {
2765 *exit_status = EXIT_USER;
12145637 2766 log_unit_error(unit, "GID validation failed for \""GID_FMT"\"", gid);
29206d46
LP
2767 return -ESRCH;
2768 }
5bc7452b 2769
29206d46
LP
2770 if (dcreds->user)
2771 username = dcreds->user->name;
2772
2773 } else {
4d885bd3
DH
2774 r = get_fixed_user(context, &username, &uid, &gid, &home, &shell);
2775 if (r < 0) {
2776 *exit_status = EXIT_USER;
12145637 2777 return log_unit_error_errno(unit, r, "Failed to determine user credentials: %m");
5bc7452b 2778 }
5bc7452b 2779
4d885bd3
DH
2780 r = get_fixed_group(context, &groupname, &gid);
2781 if (r < 0) {
2782 *exit_status = EXIT_GROUP;
12145637 2783 return log_unit_error_errno(unit, r, "Failed to determine group credentials: %m");
4d885bd3 2784 }
cdc5d5c5 2785 }
29206d46 2786
cdc5d5c5
DH
2787 /* Initialize user supplementary groups and get SupplementaryGroups= ones */
2788 r = get_supplementary_groups(context, username, groupname, gid,
2789 &supplementary_gids, &ngids);
2790 if (r < 0) {
2791 *exit_status = EXIT_GROUP;
12145637 2792 return log_unit_error_errno(unit, r, "Failed to determine supplementary groups: %m");
29206d46 2793 }
5bc7452b 2794
00d9ef85
LP
2795 r = send_user_lookup(unit, user_lookup_fd, uid, gid);
2796 if (r < 0) {
2797 *exit_status = EXIT_USER;
12145637 2798 return log_unit_error_errno(unit, r, "Failed to send user credentials to PID1: %m");
00d9ef85
LP
2799 }
2800
2801 user_lookup_fd = safe_close(user_lookup_fd);
2802
6732edab
LP
2803 r = acquire_home(context, uid, &home, &home_buffer);
2804 if (r < 0) {
2805 *exit_status = EXIT_CHDIR;
12145637 2806 return log_unit_error_errno(unit, r, "Failed to determine $HOME for user: %m");
6732edab
LP
2807 }
2808
d35fbf6b
DM
2809 /* If a socket is connected to STDIN/STDOUT/STDERR, we
2810 * must sure to drop O_NONBLOCK */
2811 if (socket_fd >= 0)
a34ceba6 2812 (void) fd_nonblock(socket_fd, false);
acbb0225 2813
52c239d7 2814 r = setup_input(context, params, socket_fd, named_iofds);
ff0af2a1
LP
2815 if (r < 0) {
2816 *exit_status = EXIT_STDIN;
12145637 2817 return log_unit_error_errno(unit, r, "Failed to set up standard input: %m");
d35fbf6b 2818 }
034c6ed7 2819
52c239d7 2820 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
2821 if (r < 0) {
2822 *exit_status = EXIT_STDOUT;
12145637 2823 return log_unit_error_errno(unit, r, "Failed to set up standard output: %m");
d35fbf6b
DM
2824 }
2825
52c239d7 2826 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
2827 if (r < 0) {
2828 *exit_status = EXIT_STDERR;
12145637 2829 return log_unit_error_errno(unit, r, "Failed to set up standard error output: %m");
d35fbf6b
DM
2830 }
2831
2832 if (params->cgroup_path) {
ff0af2a1
LP
2833 r = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0, NULL, NULL);
2834 if (r < 0) {
2835 *exit_status = EXIT_CGROUP;
12145637 2836 return log_unit_error_errno(unit, r, "Failed to attach to cgroup %s: %m", params->cgroup_path);
309bff19 2837 }
d35fbf6b 2838 }
309bff19 2839
d35fbf6b 2840 if (context->oom_score_adjust_set) {
d5243d62 2841 char t[DECIMAL_STR_MAX(context->oom_score_adjust)];
f2b68789 2842
d5243d62
LP
2843 /* When we can't make this change due to EPERM, then
2844 * let's silently skip over it. User namespaces
2845 * prohibit write access to this file, and we
2846 * shouldn't trip up over that. */
613b411c 2847
d5243d62 2848 sprintf(t, "%i", context->oom_score_adjust);
ad118bda 2849 r = write_string_file("/proc/self/oom_score_adj", t, 0);
12145637 2850 if (IN_SET(r, -EPERM, -EACCES))
f2341e0a 2851 log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
12145637 2852 else if (r < 0) {
ff0af2a1 2853 *exit_status = EXIT_OOM_ADJUST;
12145637 2854 return log_unit_error_errno(unit, r, "Failed to adjust OOM setting: %m");
613b411c 2855 }
d35fbf6b
DM
2856 }
2857
2858 if (context->nice_set)
2859 if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
ff0af2a1 2860 *exit_status = EXIT_NICE;
12145637 2861 return log_unit_error_errno(unit, errno, "Failed to set up process scheduling priority (nice level): %m");
613b411c
LP
2862 }
2863
d35fbf6b
DM
2864 if (context->cpu_sched_set) {
2865 struct sched_param param = {
2866 .sched_priority = context->cpu_sched_priority,
2867 };
2868
ff0af2a1
LP
2869 r = sched_setscheduler(0,
2870 context->cpu_sched_policy |
2871 (context->cpu_sched_reset_on_fork ?
2872 SCHED_RESET_ON_FORK : 0),
2873 &param);
2874 if (r < 0) {
2875 *exit_status = EXIT_SETSCHEDULER;
12145637 2876 return log_unit_error_errno(unit, errno, "Failed to set up CPU scheduling: %m");
fc9b2a84 2877 }
d35fbf6b 2878 }
fc9b2a84 2879
d35fbf6b
DM
2880 if (context->cpuset)
2881 if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
ff0af2a1 2882 *exit_status = EXIT_CPUAFFINITY;
12145637 2883 return log_unit_error_errno(unit, errno, "Failed to set up CPU affinity: %m");
034c6ed7
LP
2884 }
2885
d35fbf6b
DM
2886 if (context->ioprio_set)
2887 if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
ff0af2a1 2888 *exit_status = EXIT_IOPRIO;
12145637 2889 return log_unit_error_errno(unit, errno, "Failed to set up IO scheduling priority: %m");
d35fbf6b 2890 }
da726a4d 2891
d35fbf6b
DM
2892 if (context->timer_slack_nsec != NSEC_INFINITY)
2893 if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
ff0af2a1 2894 *exit_status = EXIT_TIMERSLACK;
12145637 2895 return log_unit_error_errno(unit, errno, "Failed to set up timer slack: %m");
4c2630eb 2896 }
9eba9da4 2897
21022b9d
LP
2898 if (context->personality != PERSONALITY_INVALID) {
2899 r = safe_personality(context->personality);
2900 if (r < 0) {
ff0af2a1 2901 *exit_status = EXIT_PERSONALITY;
12145637 2902 return log_unit_error_errno(unit, r, "Failed to set up execution domain (personality): %m");
4c2630eb 2903 }
21022b9d 2904 }
94f04347 2905
d35fbf6b 2906 if (context->utmp_id)
df0ff127 2907 utmp_put_init_process(context->utmp_id, getpid_cached(), getsid(0),
6a93917d 2908 context->tty_path,
023a4f67
LP
2909 context->utmp_mode == EXEC_UTMP_INIT ? INIT_PROCESS :
2910 context->utmp_mode == EXEC_UTMP_LOGIN ? LOGIN_PROCESS :
2911 USER_PROCESS,
6a93917d 2912 username);
d35fbf6b 2913
e0d2adfd 2914 if (context->user) {
ff0af2a1
LP
2915 r = chown_terminal(STDIN_FILENO, uid);
2916 if (r < 0) {
2917 *exit_status = EXIT_STDIN;
12145637 2918 return log_unit_error_errno(unit, r, "Failed to change ownership of terminal: %m");
071830ff 2919 }
d35fbf6b 2920 }
8e274523 2921
a931ad47
LP
2922 /* If delegation is enabled we'll pass ownership of the cgroup
2923 * (but only in systemd's own controller hierarchy!) to the
2924 * user of the new process. */
584b8688 2925 if (params->cgroup_path && context->user && (params->flags & EXEC_CGROUP_DELEGATE)) {
ff0af2a1
LP
2926 r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0644, 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");
d35fbf6b 2930 }
034c6ed7 2931
ff0af2a1
LP
2932 r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0755, uid, gid);
2933 if (r < 0) {
2934 *exit_status = EXIT_CGROUP;
12145637 2935 return log_unit_error_errno(unit, r, "Failed to adjust control group access: %m");
034c6ed7 2936 }
d35fbf6b 2937 }
034c6ed7 2938
72fd1768 2939 for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) {
8679efde 2940 r = setup_exec_directory(context, params, uid, gid, dt, exit_status);
12145637
LP
2941 if (r < 0)
2942 return log_unit_error_errno(unit, r, "Failed to set up special execution directory in %s: %m", params->prefix[dt]);
d35fbf6b 2943 }
94f04347 2944
7bce046b 2945 r = build_environment(
fd63e712 2946 unit,
7bce046b
LP
2947 context,
2948 params,
2949 n_fds,
2950 home,
2951 username,
2952 shell,
2953 journal_stream_dev,
2954 journal_stream_ino,
2955 &our_env);
2065ca69
JW
2956 if (r < 0) {
2957 *exit_status = EXIT_MEMORY;
12145637 2958 return log_oom();
2065ca69
JW
2959 }
2960
2961 r = build_pass_environment(context, &pass_env);
2962 if (r < 0) {
2963 *exit_status = EXIT_MEMORY;
12145637 2964 return log_oom();
2065ca69
JW
2965 }
2966
2967 accum_env = strv_env_merge(5,
2968 params->environment,
2969 our_env,
2970 pass_env,
2971 context->environment,
2972 files_env,
2973 NULL);
2974 if (!accum_env) {
2975 *exit_status = EXIT_MEMORY;
12145637 2976 return log_oom();
2065ca69 2977 }
1280503b 2978 accum_env = strv_env_clean(accum_env);
2065ca69 2979
096424d1 2980 (void) umask(context->umask);
b213e1c1 2981
b1edf445 2982 r = setup_keyring(unit, context, params, uid, gid);
74dd6b51
LP
2983 if (r < 0) {
2984 *exit_status = EXIT_KEYRING;
12145637 2985 return log_unit_error_errno(unit, r, "Failed to set up kernel keyring: %m");
74dd6b51
LP
2986 }
2987
165a31c0 2988 /* We need sandboxing if the caller asked us to apply it and the command isn't explicitly excepted from it */
1703fa41 2989 needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & EXEC_COMMAND_FULLY_PRIVILEGED);
7f18ef0a 2990
165a31c0
LP
2991 /* 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 */
2992 needs_ambient_hack = (params->flags & EXEC_APPLY_SANDBOXING) && (command->flags & EXEC_COMMAND_AMBIENT_MAGIC) && !ambient_capabilities_supported();
7f18ef0a 2993
165a31c0
LP
2994 /* 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 */
2995 if (needs_ambient_hack)
2996 needs_setuid = false;
2997 else
2998 needs_setuid = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID));
2999
3000 if (needs_sandboxing) {
7f18ef0a
FK
3001 /* MAC enablement checks need to be done before a new mount ns is created, as they rely on /sys being
3002 * present. The actual MAC context application will happen later, as late as possible, to avoid
3003 * impacting our own code paths. */
3004
349cc4a5 3005#if HAVE_SELINUX
43b1f709 3006 use_selinux = mac_selinux_use();
7f18ef0a 3007#endif
f9fa32f0 3008#if ENABLE_SMACK
43b1f709 3009 use_smack = mac_smack_use();
7f18ef0a 3010#endif
349cc4a5 3011#if HAVE_APPARMOR
43b1f709 3012 use_apparmor = mac_apparmor_use();
7f18ef0a 3013#endif
165a31c0 3014 }
7f18ef0a 3015
165a31c0
LP
3016 if (needs_setuid) {
3017 if (context->pam_name && username) {
3018 r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds);
3019 if (r < 0) {
3020 *exit_status = EXIT_PAM;
12145637 3021 return log_unit_error_errno(unit, r, "Failed to set up PAM session: %m");
165a31c0
LP
3022 }
3023 }
b213e1c1 3024 }
ac45f971 3025
d35fbf6b 3026 if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) {
6e2d7c4f
MS
3027 if (ns_type_supported(NAMESPACE_NET)) {
3028 r = setup_netns(runtime->netns_storage_socket);
3029 if (r < 0) {
3030 *exit_status = EXIT_NETWORK;
3031 return log_unit_error_errno(unit, r, "Failed to set up network namespacing: %m");
3032 }
3033 } else
3034 log_unit_warning(unit, "PrivateNetwork=yes is configured, but the kernel does not support network namespaces, ignoring.");
d35fbf6b 3035 }
169c1bda 3036
ee818b89 3037 needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime);
ee818b89 3038 if (needs_mount_namespace) {
6818c54c 3039 r = apply_mount_namespace(unit, command, context, params, runtime);
3fbe8dbe
LP
3040 if (r < 0) {
3041 *exit_status = EXIT_NAMESPACE;
12145637 3042 return log_unit_error_errno(unit, r, "Failed to set up mount namespacing: %m");
3fbe8dbe 3043 }
d35fbf6b 3044 }
81a2b7ce 3045
50b3dfb9 3046 /* Apply just after mount namespace setup */
376fecf6 3047 r = apply_working_directory(context, params, home, needs_mount_namespace, exit_status);
12145637
LP
3048 if (r < 0)
3049 return log_unit_error_errno(unit, r, "Changing to the requested working directory failed: %m");
50b3dfb9 3050
bbeea271 3051 /* Drop groups as early as possbile */
165a31c0 3052 if (needs_setuid) {
709dbeac 3053 r = enforce_groups(gid, supplementary_gids, ngids);
096424d1
LP
3054 if (r < 0) {
3055 *exit_status = EXIT_GROUP;
12145637 3056 return log_unit_error_errno(unit, r, "Changing group credentials failed: %m");
096424d1 3057 }
165a31c0 3058 }
096424d1 3059
165a31c0 3060 if (needs_sandboxing) {
349cc4a5 3061#if HAVE_SELINUX
43b1f709 3062 if (use_selinux && params->selinux_context_net && socket_fd >= 0) {
937ccce9
LP
3063 r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net);
3064 if (r < 0) {
3065 *exit_status = EXIT_SELINUX_CONTEXT;
12145637 3066 return log_unit_error_errno(unit, r, "Failed to determine SELinux context: %m");
937ccce9 3067 }
9008e1ac 3068 }
9008e1ac
MS
3069#endif
3070
937ccce9
LP
3071 if (context->private_users) {
3072 r = setup_private_users(uid, gid);
3073 if (r < 0) {
3074 *exit_status = EXIT_USER;
12145637 3075 return log_unit_error_errno(unit, r, "Failed to set up user namespacing: %m");
937ccce9 3076 }
d251207d
LP
3077 }
3078 }
3079
165a31c0
LP
3080 /* We repeat the fd closing here, to make sure that nothing is leaked from the PAM modules. Note that we are
3081 * more aggressive this time since socket_fd and the netns fds we don't need anymore. The custom endpoint fd
3082 * was needed to upload the policy and can now be closed as well. */
ff0af2a1
LP
3083 r = close_all_fds(fds, n_fds);
3084 if (r >= 0)
3085 r = shift_fds(fds, n_fds);
3086 if (r >= 0)
4c47affc 3087 r = flags_fds(fds, n_storage_fds, n_socket_fds, context->non_blocking);
ff0af2a1
LP
3088 if (r < 0) {
3089 *exit_status = EXIT_FDS;
12145637 3090 return log_unit_error_errno(unit, r, "Failed to adjust passed file descriptors: %m");
d35fbf6b 3091 }
e66cf1a3 3092
165a31c0 3093 secure_bits = context->secure_bits;
e66cf1a3 3094
165a31c0
LP
3095 if (needs_sandboxing) {
3096 uint64_t bset;
755d4b67 3097
d35fbf6b 3098 for (i = 0; i < _RLIMIT_MAX; i++) {
03857c43 3099
d35fbf6b
DM
3100 if (!context->rlimit[i])
3101 continue;
3102
03857c43
LP
3103 r = setrlimit_closest(i, context->rlimit[i]);
3104 if (r < 0) {
ff0af2a1 3105 *exit_status = EXIT_LIMITS;
12145637 3106 return log_unit_error_errno(unit, r, "Failed to adjust resource limit %s: %m", rlimit_to_string(i));
e66cf1a3
LP
3107 }
3108 }
3109
f4170c67
LP
3110 /* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly requested. */
3111 if (context->restrict_realtime && !context->rlimit[RLIMIT_RTPRIO]) {
3112 if (setrlimit(RLIMIT_RTPRIO, &RLIMIT_MAKE_CONST(0)) < 0) {
3113 *exit_status = EXIT_LIMITS;
12145637 3114 return log_unit_error_errno(unit, errno, "Failed to adjust RLIMIT_RTPRIO resource limit: %m");
f4170c67
LP
3115 }
3116 }
3117
165a31c0
LP
3118 bset = context->capability_bounding_set;
3119 /* If the ambient caps hack is enabled (which means the kernel can't do them, and the user asked for
3120 * our magic fallback), then let's add some extra caps, so that the service can drop privs of its own,
3121 * instead of us doing that */
3122 if (needs_ambient_hack)
3123 bset |= (UINT64_C(1) << CAP_SETPCAP) |
3124 (UINT64_C(1) << CAP_SETUID) |
3125 (UINT64_C(1) << CAP_SETGID);
3126
3127 if (!cap_test_all(bset)) {
3128 r = capability_bounding_set_drop(bset, false);
ff0af2a1
LP
3129 if (r < 0) {
3130 *exit_status = EXIT_CAPABILITIES;
12145637 3131 return log_unit_error_errno(unit, r, "Failed to drop capabilities: %m");
3b8bddde 3132 }
4c2630eb 3133 }
3b8bddde 3134
755d4b67
IP
3135 /* This is done before enforce_user, but ambient set
3136 * does not survive over setresuid() if keep_caps is not set. */
165a31c0
LP
3137 if (!needs_ambient_hack &&
3138 context->capability_ambient_set != 0) {
755d4b67
IP
3139 r = capability_ambient_set_apply(context->capability_ambient_set, true);
3140 if (r < 0) {
3141 *exit_status = EXIT_CAPABILITIES;
12145637 3142 return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (before UID change): %m");
755d4b67 3143 }
755d4b67 3144 }
165a31c0 3145 }
755d4b67 3146
165a31c0 3147 if (needs_setuid) {
d35fbf6b 3148 if (context->user) {
ff0af2a1
LP
3149 r = enforce_user(context, uid);
3150 if (r < 0) {
3151 *exit_status = EXIT_USER;
12145637 3152 return log_unit_error_errno(unit, r, "Failed to change UID to " UID_FMT ": %m", uid);
5b6319dc 3153 }
165a31c0
LP
3154
3155 if (!needs_ambient_hack &&
3156 context->capability_ambient_set != 0) {
755d4b67
IP
3157
3158 /* Fix the ambient capabilities after user change. */
3159 r = capability_ambient_set_apply(context->capability_ambient_set, false);
3160 if (r < 0) {
3161 *exit_status = EXIT_CAPABILITIES;
12145637 3162 return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (after UID change): %m");
755d4b67
IP
3163 }
3164
3165 /* If we were asked to change user and ambient capabilities
3166 * were requested, we had to add keep-caps to the securebits
3167 * so that we would maintain the inherited capability set
3168 * through the setresuid(). Make sure that the bit is added
3169 * also to the context secure_bits so that we don't try to
3170 * drop the bit away next. */
3171
7f508f2c 3172 secure_bits |= 1<<SECURE_KEEP_CAPS;
755d4b67 3173 }
5b6319dc 3174 }
165a31c0 3175 }
d35fbf6b 3176
165a31c0 3177 if (needs_sandboxing) {
5cd9cd35
LP
3178 /* Apply the MAC contexts late, but before seccomp syscall filtering, as those should really be last to
3179 * influence our own codepaths as little as possible. Moreover, applying MAC contexts usually requires
3180 * syscalls that are subject to seccomp filtering, hence should probably be applied before the syscalls
3181 * are restricted. */
3182
349cc4a5 3183#if HAVE_SELINUX
43b1f709 3184 if (use_selinux) {
5cd9cd35
LP
3185 char *exec_context = mac_selinux_context_net ?: context->selinux_context;
3186
3187 if (exec_context) {
3188 r = setexeccon(exec_context);
3189 if (r < 0) {
3190 *exit_status = EXIT_SELINUX_CONTEXT;
12145637 3191 return log_unit_error_errno(unit, r, "Failed to change SELinux context to %s: %m", exec_context);
5cd9cd35
LP
3192 }
3193 }
3194 }
3195#endif
3196
f9fa32f0 3197#if ENABLE_SMACK
43b1f709 3198 if (use_smack) {
7f18ef0a
FK
3199 r = setup_smack(context, command);
3200 if (r < 0) {
3201 *exit_status = EXIT_SMACK_PROCESS_LABEL;
12145637 3202 return log_unit_error_errno(unit, r, "Failed to set SMACK process label: %m");
7f18ef0a 3203 }
5cd9cd35 3204 }
7f18ef0a 3205#endif
5cd9cd35 3206
349cc4a5 3207#if HAVE_APPARMOR
43b1f709 3208 if (use_apparmor && context->apparmor_profile) {
5cd9cd35
LP
3209 r = aa_change_onexec(context->apparmor_profile);
3210 if (r < 0 && !context->apparmor_profile_ignore) {
3211 *exit_status = EXIT_APPARMOR_PROFILE;
12145637 3212 return log_unit_error_errno(unit, errno, "Failed to prepare AppArmor profile change to %s: %m", context->apparmor_profile);
5cd9cd35
LP
3213 }
3214 }
3215#endif
3216
165a31c0
LP
3217 /* PR_GET_SECUREBITS is not privileged, while PR_SET_SECUREBITS is. So to suppress potential EPERMs
3218 * we'll try not to call PR_SET_SECUREBITS unless necessary. */
755d4b67
IP
3219 if (prctl(PR_GET_SECUREBITS) != secure_bits)
3220 if (prctl(PR_SET_SECUREBITS, secure_bits) < 0) {
ff0af2a1 3221 *exit_status = EXIT_SECUREBITS;
12145637 3222 return log_unit_error_errno(unit, errno, "Failed to set process secure bits: %m");
ff01d048 3223 }
5b6319dc 3224
59eeb84b 3225 if (context_has_no_new_privileges(context))
d35fbf6b 3226 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
ff0af2a1 3227 *exit_status = EXIT_NO_NEW_PRIVILEGES;
12145637 3228 return log_unit_error_errno(unit, errno, "Failed to disable new privileges: %m");
d35fbf6b
DM
3229 }
3230
349cc4a5 3231#if HAVE_SECCOMP
469830d1
LP
3232 r = apply_address_families(unit, context);
3233 if (r < 0) {
3234 *exit_status = EXIT_ADDRESS_FAMILIES;
12145637 3235 return log_unit_error_errno(unit, r, "Failed to restrict address families: %m");
4c2630eb 3236 }
04aa0cb9 3237
469830d1
LP
3238 r = apply_memory_deny_write_execute(unit, context);
3239 if (r < 0) {
3240 *exit_status = EXIT_SECCOMP;
12145637 3241 return log_unit_error_errno(unit, r, "Failed to disable writing to executable memory: %m");
f3e43635 3242 }
f4170c67 3243
469830d1
LP
3244 r = apply_restrict_realtime(unit, context);
3245 if (r < 0) {
3246 *exit_status = EXIT_SECCOMP;
12145637 3247 return log_unit_error_errno(unit, r, "Failed to apply realtime restrictions: %m");
f4170c67
LP
3248 }
3249
add00535
LP
3250 r = apply_restrict_namespaces(unit, context);
3251 if (r < 0) {
3252 *exit_status = EXIT_SECCOMP;
12145637 3253 return log_unit_error_errno(unit, r, "Failed to apply namespace restrictions: %m");
add00535
LP
3254 }
3255
469830d1
LP
3256 r = apply_protect_sysctl(unit, context);
3257 if (r < 0) {
3258 *exit_status = EXIT_SECCOMP;
12145637 3259 return log_unit_error_errno(unit, r, "Failed to apply sysctl restrictions: %m");
502d704e
DH
3260 }
3261
469830d1
LP
3262 r = apply_protect_kernel_modules(unit, context);
3263 if (r < 0) {
3264 *exit_status = EXIT_SECCOMP;
12145637 3265 return log_unit_error_errno(unit, r, "Failed to apply module loading restrictions: %m");
59eeb84b
LP
3266 }
3267
469830d1
LP
3268 r = apply_private_devices(unit, context);
3269 if (r < 0) {
3270 *exit_status = EXIT_SECCOMP;
12145637 3271 return log_unit_error_errno(unit, r, "Failed to set up private devices: %m");
469830d1
LP
3272 }
3273
3274 r = apply_syscall_archs(unit, context);
3275 if (r < 0) {
3276 *exit_status = EXIT_SECCOMP;
12145637 3277 return log_unit_error_errno(unit, r, "Failed to apply syscall architecture restrictions: %m");
ba128bb8
LP
3278 }
3279
78e864e5
TM
3280 r = apply_lock_personality(unit, context);
3281 if (r < 0) {
3282 *exit_status = EXIT_SECCOMP;
12145637 3283 return log_unit_error_errno(unit, r, "Failed to lock personalities: %m");
78e864e5
TM
3284 }
3285
5cd9cd35
LP
3286 /* This really should remain the last step before the execve(), to make sure our own code is unaffected
3287 * by the filter as little as possible. */
165a31c0 3288 r = apply_syscall_filter(unit, context, needs_ambient_hack);
469830d1
LP
3289 if (r < 0) {
3290 *exit_status = EXIT_SECCOMP;
12145637 3291 return log_unit_error_errno(unit, r, "Failed to apply system call filters: %m");
d35fbf6b
DM
3292 }
3293#endif
d35fbf6b 3294 }
034c6ed7 3295
00819cc1
LP
3296 if (!strv_isempty(context->unset_environment)) {
3297 char **ee = NULL;
3298
3299 ee = strv_env_delete(accum_env, 1, context->unset_environment);
3300 if (!ee) {
3301 *exit_status = EXIT_MEMORY;
12145637 3302 return log_oom();
00819cc1
LP
3303 }
3304
3305 strv_free(accum_env);
3306 accum_env = ee;
3307 }
3308
2065ca69 3309 final_argv = replace_env_argv(argv, accum_env);
d35fbf6b 3310 if (!final_argv) {
ff0af2a1 3311 *exit_status = EXIT_MEMORY;
12145637 3312 return log_oom();
d35fbf6b 3313 }
034c6ed7 3314
553d2243 3315 if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
d35fbf6b 3316 _cleanup_free_ char *line;
81a2b7ce 3317
d35fbf6b
DM
3318 line = exec_command_line(final_argv);
3319 if (line) {
f2341e0a 3320 log_struct(LOG_DEBUG,
f2341e0a
LP
3321 "EXECUTABLE=%s", command->path,
3322 LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
ba360bb0 3323 LOG_UNIT_ID(unit),
f1c50bec 3324 LOG_UNIT_INVOCATION_ID(unit),
f2341e0a 3325 NULL);
d35fbf6b
DM
3326 }
3327 }
dd305ec9 3328
2065ca69 3329 execve(command->path, final_argv, accum_env);
12145637
LP
3330
3331 if (errno == ENOENT && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
3332
3333 log_struct_errno(LOG_INFO, errno,
3334 "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
3335 LOG_UNIT_ID(unit),
3336 LOG_UNIT_INVOCATION_ID(unit),
3337 LOG_UNIT_MESSAGE(unit, "Executable %s missing, skipping: %m",
3338 command->path),
3339 "EXECUTABLE=%s", command->path,
3340 NULL);
3341
3342 return 0;
3343 }
3344
ff0af2a1 3345 *exit_status = EXIT_EXEC;
12145637 3346 return log_unit_error_errno(unit, errno, "Failed to execute command: %m");
d35fbf6b 3347}
81a2b7ce 3348
f2341e0a
LP
3349int exec_spawn(Unit *unit,
3350 ExecCommand *command,
d35fbf6b
DM
3351 const ExecContext *context,
3352 const ExecParameters *params,
3353 ExecRuntime *runtime,
29206d46 3354 DynamicCreds *dcreds,
d35fbf6b 3355 pid_t *ret) {
8351ceae 3356
d35fbf6b 3357 _cleanup_strv_free_ char **files_env = NULL;
9b141911 3358 int *fds = NULL;
4c47affc 3359 unsigned n_storage_fds = 0, n_socket_fds = 0;
ff0af2a1
LP
3360 _cleanup_free_ char *line = NULL;
3361 int socket_fd, r;
52c239d7 3362 int named_iofds[3] = { -1, -1, -1 };
ff0af2a1 3363 char **argv;
d35fbf6b 3364 pid_t pid;
8351ceae 3365
f2341e0a 3366 assert(unit);
d35fbf6b
DM
3367 assert(command);
3368 assert(context);
3369 assert(ret);
3370 assert(params);
4c47affc 3371 assert(params->fds || (params->n_storage_fds + params->n_socket_fds <= 0));
4298d0b5 3372
d35fbf6b
DM
3373 if (context->std_input == EXEC_INPUT_SOCKET ||
3374 context->std_output == EXEC_OUTPUT_SOCKET ||
3375 context->std_error == EXEC_OUTPUT_SOCKET) {
17df7223 3376
4c47affc 3377 if (params->n_socket_fds > 1) {
f2341e0a 3378 log_unit_error(unit, "Got more than one socket.");
d35fbf6b 3379 return -EINVAL;
ff0af2a1 3380 }
eef65bf3 3381
4c47affc 3382 if (params->n_socket_fds == 0) {
488ab41c
AA
3383 log_unit_error(unit, "Got no socket.");
3384 return -EINVAL;
3385 }
3386
d35fbf6b
DM
3387 socket_fd = params->fds[0];
3388 } else {
3389 socket_fd = -1;
3390 fds = params->fds;
4c47affc 3391 n_storage_fds = params->n_storage_fds;
9b141911 3392 n_socket_fds = params->n_socket_fds;
d35fbf6b 3393 }
94f04347 3394
52c239d7
LB
3395 r = exec_context_named_iofds(unit, context, params, named_iofds);
3396 if (r < 0)
3397 return log_unit_error_errno(unit, r, "Failed to load a named file descriptor: %m");
3398
f2341e0a 3399 r = exec_context_load_environment(unit, context, &files_env);
ff0af2a1 3400 if (r < 0)
f2341e0a 3401 return log_unit_error_errno(unit, r, "Failed to load environment files: %m");
034c6ed7 3402
d35fbf6b 3403 argv = params->argv ?: command->argv;
d35fbf6b
DM
3404 line = exec_command_line(argv);
3405 if (!line)
3406 return log_oom();
fab56fc5 3407
f2341e0a 3408 log_struct(LOG_DEBUG,
f2341e0a
LP
3409 LOG_UNIT_MESSAGE(unit, "About to execute: %s", line),
3410 "EXECUTABLE=%s", command->path,
ba360bb0 3411 LOG_UNIT_ID(unit),
f1c50bec 3412 LOG_UNIT_INVOCATION_ID(unit),
f2341e0a 3413 NULL);
12145637 3414
d35fbf6b
DM
3415 pid = fork();
3416 if (pid < 0)
74129a12 3417 return log_unit_error_errno(unit, errno, "Failed to fork: %m");
d35fbf6b
DM
3418
3419 if (pid == 0) {
12145637 3420 int exit_status = EXIT_SUCCESS;
ff0af2a1 3421
f2341e0a
LP
3422 r = exec_child(unit,
3423 command,
ff0af2a1
LP
3424 context,
3425 params,
3426 runtime,
29206d46 3427 dcreds,
ff0af2a1
LP
3428 argv,
3429 socket_fd,
52c239d7 3430 named_iofds,
4c47affc
FB
3431 fds,
3432 n_storage_fds,
9b141911 3433 n_socket_fds,
ff0af2a1 3434 files_env,
00d9ef85 3435 unit->manager->user_lookup_fds[1],
12145637
LP
3436 &exit_status);
3437
ff0af2a1 3438 if (r < 0) {
12145637
LP
3439 log_struct_errno(LOG_ERR, r,
3440 "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
3441 LOG_UNIT_ID(unit),
3442 LOG_UNIT_INVOCATION_ID(unit),
3443 LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
3444 exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD),
3445 command->path),
3446 "EXECUTABLE=%s", command->path,
3447 NULL);
4c2630eb
MS
3448 }
3449
ff0af2a1 3450 _exit(exit_status);
034c6ed7
LP
3451 }
3452
f2341e0a 3453 log_unit_debug(unit, "Forked %s as "PID_FMT, command->path, pid);
23635a85 3454
80876c20
LP
3455 /* We add the new process to the cgroup both in the child (so
3456 * that we can be sure that no user code is ever executed
3457 * outside of the cgroup) and in the parent (so that we can be
3458 * sure that when we kill the cgroup the process will be
3459 * killed too). */
d35fbf6b 3460 if (params->cgroup_path)
dd305ec9 3461 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, pid);
2da3263a 3462
b58b4116 3463 exec_status_start(&command->exec_status, pid);
9fb86720 3464
034c6ed7 3465 *ret = pid;
5cb5a6ff
LP
3466 return 0;
3467}
3468
034c6ed7 3469void exec_context_init(ExecContext *c) {
3536f49e
YW
3470 ExecDirectoryType i;
3471
034c6ed7
LP
3472 assert(c);
3473
4c12626c 3474 c->umask = 0022;
9eba9da4 3475 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
94f04347 3476 c->cpu_sched_policy = SCHED_OTHER;
071830ff 3477 c->syslog_priority = LOG_DAEMON|LOG_INFO;
74922904 3478 c->syslog_level_prefix = true;
353e12c2 3479 c->ignore_sigpipe = true;
3a43da28 3480 c->timer_slack_nsec = NSEC_INFINITY;
050f7277 3481 c->personality = PERSONALITY_INVALID;
72fd1768 3482 for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
3536f49e 3483 c->directories[i].mode = 0755;
a103496c 3484 c->capability_bounding_set = CAP_ALL;
add00535 3485 c->restrict_namespaces = NAMESPACE_FLAGS_ALL;
d3070fbd 3486 c->log_level_max = -1;
034c6ed7
LP
3487}
3488
613b411c 3489void exec_context_done(ExecContext *c) {
3536f49e 3490 ExecDirectoryType i;
d3070fbd 3491 size_t l;
5cb5a6ff
LP
3492
3493 assert(c);
3494
6796073e
LP
3495 c->environment = strv_free(c->environment);
3496 c->environment_files = strv_free(c->environment_files);
b4c14404 3497 c->pass_environment = strv_free(c->pass_environment);
00819cc1 3498 c->unset_environment = strv_free(c->unset_environment);
8c7be95e 3499
1f6b4113 3500 for (l = 0; l < ELEMENTSOF(c->rlimit); l++)
a1e58e8e 3501 c->rlimit[l] = mfree(c->rlimit[l]);
034c6ed7 3502
52c239d7
LB
3503 for (l = 0; l < 3; l++)
3504 c->stdio_fdname[l] = mfree(c->stdio_fdname[l]);
3505
a1e58e8e
LP
3506 c->working_directory = mfree(c->working_directory);
3507 c->root_directory = mfree(c->root_directory);
915e6d16 3508 c->root_image = mfree(c->root_image);
a1e58e8e
LP
3509 c->tty_path = mfree(c->tty_path);
3510 c->syslog_identifier = mfree(c->syslog_identifier);
3511 c->user = mfree(c->user);
3512 c->group = mfree(c->group);
034c6ed7 3513
6796073e 3514 c->supplementary_groups = strv_free(c->supplementary_groups);
94f04347 3515
a1e58e8e 3516 c->pam_name = mfree(c->pam_name);
5b6319dc 3517
2a624c36
AP
3518 c->read_only_paths = strv_free(c->read_only_paths);
3519 c->read_write_paths = strv_free(c->read_write_paths);
3520 c->inaccessible_paths = strv_free(c->inaccessible_paths);
82c121a4 3521
d2d6c096
LP
3522 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
3523
82c121a4
LP
3524 if (c->cpuset)
3525 CPU_FREE(c->cpuset);
86a3475b 3526
a1e58e8e
LP
3527 c->utmp_id = mfree(c->utmp_id);
3528 c->selinux_context = mfree(c->selinux_context);
3529 c->apparmor_profile = mfree(c->apparmor_profile);
5b8e1b77 3530 c->smack_process_label = mfree(c->smack_process_label);
eef65bf3 3531
8cfa775f 3532 c->syscall_filter = hashmap_free(c->syscall_filter);
525d3cc7
LP
3533 c->syscall_archs = set_free(c->syscall_archs);
3534 c->address_families = set_free(c->address_families);
e66cf1a3 3535
72fd1768 3536 for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
3536f49e 3537 c->directories[i].paths = strv_free(c->directories[i].paths);
d3070fbd
LP
3538
3539 c->log_level_max = -1;
3540
3541 exec_context_free_log_extra_fields(c);
08f3be7a
LP
3542
3543 c->stdin_data = mfree(c->stdin_data);
3544 c->stdin_data_size = 0;
e66cf1a3
LP
3545}
3546
3547int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_prefix) {
3548 char **i;
3549
3550 assert(c);
3551
3552 if (!runtime_prefix)
3553 return 0;
3554
3536f49e 3555 STRV_FOREACH(i, c->directories[EXEC_DIRECTORY_RUNTIME].paths) {
e66cf1a3
LP
3556 _cleanup_free_ char *p;
3557
605405c6 3558 p = strjoin(runtime_prefix, "/", *i);
e66cf1a3
LP
3559 if (!p)
3560 return -ENOMEM;
3561
6c47cd7d 3562 /* We execute this synchronously, since we need to be sure this is gone when we start the service
e66cf1a3 3563 * next. */
c6878637 3564 (void) rm_rf(p, REMOVE_ROOT);
e66cf1a3
LP
3565 }
3566
3567 return 0;
5cb5a6ff
LP
3568}
3569
43d0fcbd
LP
3570void exec_command_done(ExecCommand *c) {
3571 assert(c);
3572
a1e58e8e 3573 c->path = mfree(c->path);
43d0fcbd 3574
6796073e 3575 c->argv = strv_free(c->argv);
43d0fcbd
LP
3576}
3577
3578void exec_command_done_array(ExecCommand *c, unsigned n) {
3579 unsigned i;
3580
3581 for (i = 0; i < n; i++)
3582 exec_command_done(c+i);
3583}
3584
f1acf85a 3585ExecCommand* exec_command_free_list(ExecCommand *c) {
5cb5a6ff
LP
3586 ExecCommand *i;
3587
3588 while ((i = c)) {
71fda00f 3589 LIST_REMOVE(command, c, i);
43d0fcbd 3590 exec_command_done(i);
5cb5a6ff
LP
3591 free(i);
3592 }
f1acf85a
ZJS
3593
3594 return NULL;
5cb5a6ff
LP
3595}
3596
034c6ed7
LP
3597void exec_command_free_array(ExecCommand **c, unsigned n) {
3598 unsigned i;
3599
f1acf85a
ZJS
3600 for (i = 0; i < n; i++)
3601 c[i] = exec_command_free_list(c[i]);
034c6ed7
LP
3602}
3603
039f0e70 3604typedef struct InvalidEnvInfo {
f2341e0a 3605 Unit *unit;
039f0e70
LP
3606 const char *path;
3607} InvalidEnvInfo;
3608
3609static void invalid_env(const char *p, void *userdata) {
3610 InvalidEnvInfo *info = userdata;
3611
f2341e0a 3612 log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path);
039f0e70
LP
3613}
3614
52c239d7
LB
3615const char* exec_context_fdname(const ExecContext *c, int fd_index) {
3616 assert(c);
3617
3618 switch (fd_index) {
5073ff6b 3619
52c239d7
LB
3620 case STDIN_FILENO:
3621 if (c->std_input != EXEC_INPUT_NAMED_FD)
3622 return NULL;
5073ff6b 3623
52c239d7 3624 return c->stdio_fdname[STDIN_FILENO] ?: "stdin";
5073ff6b 3625
52c239d7
LB
3626 case STDOUT_FILENO:
3627 if (c->std_output != EXEC_OUTPUT_NAMED_FD)
3628 return NULL;
5073ff6b 3629
52c239d7 3630 return c->stdio_fdname[STDOUT_FILENO] ?: "stdout";
5073ff6b 3631
52c239d7
LB
3632 case STDERR_FILENO:
3633 if (c->std_error != EXEC_OUTPUT_NAMED_FD)
3634 return NULL;
5073ff6b 3635
52c239d7 3636 return c->stdio_fdname[STDERR_FILENO] ?: "stderr";
5073ff6b 3637
52c239d7
LB
3638 default:
3639 return NULL;
3640 }
3641}
3642
3643int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]) {
3644 unsigned i, targets;
56fbd561 3645 const char* stdio_fdname[3];
4c47affc 3646 unsigned n_fds;
52c239d7
LB
3647
3648 assert(c);
3649 assert(p);
3650
3651 targets = (c->std_input == EXEC_INPUT_NAMED_FD) +
3652 (c->std_output == EXEC_OUTPUT_NAMED_FD) +
3653 (c->std_error == EXEC_OUTPUT_NAMED_FD);
3654
3655 for (i = 0; i < 3; i++)
3656 stdio_fdname[i] = exec_context_fdname(c, i);
3657
4c47affc
FB
3658 n_fds = p->n_storage_fds + p->n_socket_fds;
3659
3660 for (i = 0; i < n_fds && targets > 0; i++)
56fbd561
ZJS
3661 if (named_iofds[STDIN_FILENO] < 0 &&
3662 c->std_input == EXEC_INPUT_NAMED_FD &&
3663 stdio_fdname[STDIN_FILENO] &&
3664 streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) {
3665
52c239d7
LB
3666 named_iofds[STDIN_FILENO] = p->fds[i];
3667 targets--;
56fbd561
ZJS
3668
3669 } else if (named_iofds[STDOUT_FILENO] < 0 &&
3670 c->std_output == EXEC_OUTPUT_NAMED_FD &&
3671 stdio_fdname[STDOUT_FILENO] &&
3672 streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) {
3673
52c239d7
LB
3674 named_iofds[STDOUT_FILENO] = p->fds[i];
3675 targets--;
56fbd561
ZJS
3676
3677 } else if (named_iofds[STDERR_FILENO] < 0 &&
3678 c->std_error == EXEC_OUTPUT_NAMED_FD &&
3679 stdio_fdname[STDERR_FILENO] &&
3680 streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) {
3681
52c239d7
LB
3682 named_iofds[STDERR_FILENO] = p->fds[i];
3683 targets--;
3684 }
3685
56fbd561 3686 return targets == 0 ? 0 : -ENOENT;
52c239d7
LB
3687}
3688
f2341e0a 3689int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
8c7be95e
LP
3690 char **i, **r = NULL;
3691
3692 assert(c);
3693 assert(l);
3694
3695 STRV_FOREACH(i, c->environment_files) {
3696 char *fn;
52511fae
ZJS
3697 int k;
3698 unsigned n;
8c7be95e
LP
3699 bool ignore = false;
3700 char **p;
7fd1b19b 3701 _cleanup_globfree_ glob_t pglob = {};
8c7be95e
LP
3702
3703 fn = *i;
3704
3705 if (fn[0] == '-') {
3706 ignore = true;
313cefa1 3707 fn++;
8c7be95e
LP
3708 }
3709
3710 if (!path_is_absolute(fn)) {
8c7be95e
LP
3711 if (ignore)
3712 continue;
3713
3714 strv_free(r);
3715 return -EINVAL;
3716 }
3717
2bef10ab 3718 /* Filename supports globbing, take all matching files */
d8c92e8b
ZJS
3719 k = safe_glob(fn, 0, &pglob);
3720 if (k < 0) {
2bef10ab
PL
3721 if (ignore)
3722 continue;
8c7be95e 3723
2bef10ab 3724 strv_free(r);
d8c92e8b 3725 return k;
2bef10ab 3726 }
8c7be95e 3727
d8c92e8b
ZJS
3728 /* When we don't match anything, -ENOENT should be returned */
3729 assert(pglob.gl_pathc > 0);
3730
3731 for (n = 0; n < pglob.gl_pathc; n++) {
717603e3 3732 k = load_env_file(NULL, pglob.gl_pathv[n], NULL, &p);
2bef10ab
PL
3733 if (k < 0) {
3734 if (ignore)
3735 continue;
8c7be95e 3736
2bef10ab 3737 strv_free(r);
2bef10ab 3738 return k;
e9c1ea9d 3739 }
ebc05a09 3740 /* Log invalid environment variables with filename */
039f0e70
LP
3741 if (p) {
3742 InvalidEnvInfo info = {
f2341e0a 3743 .unit = unit,
039f0e70
LP
3744 .path = pglob.gl_pathv[n]
3745 };
3746
3747 p = strv_env_clean_with_callback(p, invalid_env, &info);
3748 }
8c7be95e 3749
2bef10ab
PL
3750 if (r == NULL)
3751 r = p;
3752 else {
3753 char **m;
8c7be95e 3754
2bef10ab
PL
3755 m = strv_env_merge(2, r, p);
3756 strv_free(r);
3757 strv_free(p);
c84a9488 3758 if (!m)
2bef10ab 3759 return -ENOMEM;
2bef10ab
PL
3760
3761 r = m;
3762 }
8c7be95e
LP
3763 }
3764 }
3765
3766 *l = r;
3767
3768 return 0;
3769}
3770
6ac8fdc9 3771static bool tty_may_match_dev_console(const char *tty) {
e1d75803 3772 _cleanup_free_ char *active = NULL;
7d6884b6 3773 char *console;
6ac8fdc9 3774
1e22b5cd
LP
3775 if (!tty)
3776 return true;
3777
a119ec7c 3778 tty = skip_dev_prefix(tty);
6ac8fdc9
MS
3779
3780 /* trivial identity? */
3781 if (streq(tty, "console"))
3782 return true;
3783
3784 console = resolve_dev_console(&active);
3785 /* if we could not resolve, assume it may */
3786 if (!console)
3787 return true;
3788
3789 /* "tty0" means the active VC, so it may be the same sometimes */
e1d75803 3790 return streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty));
6ac8fdc9
MS
3791}
3792
3793bool exec_context_may_touch_console(ExecContext *ec) {
1e22b5cd
LP
3794
3795 return (ec->tty_reset ||
3796 ec->tty_vhangup ||
3797 ec->tty_vt_disallocate ||
6ac8fdc9
MS
3798 is_terminal_input(ec->std_input) ||
3799 is_terminal_output(ec->std_output) ||
3800 is_terminal_output(ec->std_error)) &&
1e22b5cd 3801 tty_may_match_dev_console(exec_context_tty_path(ec));
6ac8fdc9
MS
3802}
3803
15ae422b
LP
3804static void strv_fprintf(FILE *f, char **l) {
3805 char **g;
3806
3807 assert(f);
3808
3809 STRV_FOREACH(g, l)
3810 fprintf(f, " %s", *g);
3811}
3812
5cb5a6ff 3813void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
d3070fbd 3814 ExecDirectoryType dt;
c2bbd90b 3815 char **e, **d;
94f04347 3816 unsigned i;
add00535 3817 int r;
9eba9da4 3818
5cb5a6ff
LP
3819 assert(c);
3820 assert(f);
3821
4ad49000 3822 prefix = strempty(prefix);
5cb5a6ff
LP
3823
3824 fprintf(f,
94f04347
LP
3825 "%sUMask: %04o\n"
3826 "%sWorkingDirectory: %s\n"
451a074f 3827 "%sRootDirectory: %s\n"
15ae422b 3828 "%sNonBlocking: %s\n"
64747e2d 3829 "%sPrivateTmp: %s\n"
7f112f50 3830 "%sPrivateDevices: %s\n"
59eeb84b 3831 "%sProtectKernelTunables: %s\n"
e66a2f65 3832 "%sProtectKernelModules: %s\n"
59eeb84b 3833 "%sProtectControlGroups: %s\n"
d251207d
LP
3834 "%sPrivateNetwork: %s\n"
3835 "%sPrivateUsers: %s\n"
1b8689f9
LP
3836 "%sProtectHome: %s\n"
3837 "%sProtectSystem: %s\n"
5d997827 3838 "%sMountAPIVFS: %s\n"
f3e43635 3839 "%sIgnoreSIGPIPE: %s\n"
f4170c67 3840 "%sMemoryDenyWriteExecute: %s\n"
b1edf445
LP
3841 "%sRestrictRealtime: %s\n"
3842 "%sKeyringMode: %s\n",
5cb5a6ff 3843 prefix, c->umask,
9eba9da4 3844 prefix, c->working_directory ? c->working_directory : "/",
451a074f 3845 prefix, c->root_directory ? c->root_directory : "/",
15ae422b 3846 prefix, yes_no(c->non_blocking),
64747e2d 3847 prefix, yes_no(c->private_tmp),
7f112f50 3848 prefix, yes_no(c->private_devices),
59eeb84b 3849 prefix, yes_no(c->protect_kernel_tunables),
e66a2f65 3850 prefix, yes_no(c->protect_kernel_modules),
59eeb84b 3851 prefix, yes_no(c->protect_control_groups),
d251207d
LP
3852 prefix, yes_no(c->private_network),
3853 prefix, yes_no(c->private_users),
1b8689f9
LP
3854 prefix, protect_home_to_string(c->protect_home),
3855 prefix, protect_system_to_string(c->protect_system),
5d997827 3856 prefix, yes_no(c->mount_apivfs),
f3e43635 3857 prefix, yes_no(c->ignore_sigpipe),
f4170c67 3858 prefix, yes_no(c->memory_deny_write_execute),
b1edf445
LP
3859 prefix, yes_no(c->restrict_realtime),
3860 prefix, exec_keyring_mode_to_string(c->keyring_mode));
fb33a393 3861
915e6d16
LP
3862 if (c->root_image)
3863 fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
3864
8c7be95e
LP
3865 STRV_FOREACH(e, c->environment)
3866 fprintf(f, "%sEnvironment: %s\n", prefix, *e);
3867
3868 STRV_FOREACH(e, c->environment_files)
3869 fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
94f04347 3870
b4c14404
FB
3871 STRV_FOREACH(e, c->pass_environment)
3872 fprintf(f, "%sPassEnvironment: %s\n", prefix, *e);
3873
00819cc1
LP
3874 STRV_FOREACH(e, c->unset_environment)
3875 fprintf(f, "%sUnsetEnvironment: %s\n", prefix, *e);
3876
53f47dfc
YW
3877 fprintf(f, "%sRuntimeDirectoryPreserve: %s\n", prefix, exec_preserve_mode_to_string(c->runtime_directory_preserve_mode));
3878
72fd1768 3879 for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) {
3536f49e
YW
3880 fprintf(f, "%s%sMode: %04o\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].mode);
3881
3882 STRV_FOREACH(d, c->directories[dt].paths)
3883 fprintf(f, "%s%s: %s\n", prefix, exec_directory_type_to_string(dt), *d);
3884 }
c2bbd90b 3885
fb33a393
LP
3886 if (c->nice_set)
3887 fprintf(f,
3888 "%sNice: %i\n",
3889 prefix, c->nice);
3890
dd6c17b1 3891 if (c->oom_score_adjust_set)
fb33a393 3892 fprintf(f,
dd6c17b1
LP
3893 "%sOOMScoreAdjust: %i\n",
3894 prefix, c->oom_score_adjust);
9eba9da4 3895
94f04347 3896 for (i = 0; i < RLIM_NLIMITS; i++)
3c11da9d
EV
3897 if (c->rlimit[i]) {
3898 fprintf(f, "%s%s: " RLIM_FMT "\n",
3899 prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
3900 fprintf(f, "%s%sSoft: " RLIM_FMT "\n",
3901 prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur);
3902 }
94f04347 3903
f8b69d1d 3904 if (c->ioprio_set) {
1756a011 3905 _cleanup_free_ char *class_str = NULL;
f8b69d1d 3906
837df140
YW
3907 r = ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
3908 if (r >= 0)
3909 fprintf(f, "%sIOSchedulingClass: %s\n", prefix, class_str);
3910
3911 fprintf(f, "%sIOPriority: %lu\n", prefix, IOPRIO_PRIO_DATA(c->ioprio));
f8b69d1d 3912 }
94f04347 3913
f8b69d1d 3914 if (c->cpu_sched_set) {
1756a011 3915 _cleanup_free_ char *policy_str = NULL;
f8b69d1d 3916
837df140
YW
3917 r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
3918 if (r >= 0)
3919 fprintf(f, "%sCPUSchedulingPolicy: %s\n", prefix, policy_str);
3920
94f04347 3921 fprintf(f,
38b48754
LP
3922 "%sCPUSchedulingPriority: %i\n"
3923 "%sCPUSchedulingResetOnFork: %s\n",
38b48754
LP
3924 prefix, c->cpu_sched_priority,
3925 prefix, yes_no(c->cpu_sched_reset_on_fork));
b929bf04 3926 }
94f04347 3927
82c121a4 3928 if (c->cpuset) {
94f04347 3929 fprintf(f, "%sCPUAffinity:", prefix);
82c121a4
LP
3930 for (i = 0; i < c->cpuset_ncpus; i++)
3931 if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
43a99a7a 3932 fprintf(f, " %u", i);
94f04347
LP
3933 fputs("\n", f);
3934 }
3935
3a43da28 3936 if (c->timer_slack_nsec != NSEC_INFINITY)
ccd06097 3937 fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, c->timer_slack_nsec);
94f04347
LP
3938
3939 fprintf(f,
80876c20
LP
3940 "%sStandardInput: %s\n"
3941 "%sStandardOutput: %s\n"
3942 "%sStandardError: %s\n",
3943 prefix, exec_input_to_string(c->std_input),
3944 prefix, exec_output_to_string(c->std_output),
3945 prefix, exec_output_to_string(c->std_error));
3946
3947 if (c->tty_path)
3948 fprintf(f,
6ea832a2
LP
3949 "%sTTYPath: %s\n"
3950 "%sTTYReset: %s\n"
3951 "%sTTYVHangup: %s\n"
3952 "%sTTYVTDisallocate: %s\n",
3953 prefix, c->tty_path,
3954 prefix, yes_no(c->tty_reset),
3955 prefix, yes_no(c->tty_vhangup),
3956 prefix, yes_no(c->tty_vt_disallocate));
94f04347 3957
9f6444eb
LP
3958 if (IN_SET(c->std_output,
3959 EXEC_OUTPUT_SYSLOG,
3960 EXEC_OUTPUT_KMSG,
3961 EXEC_OUTPUT_JOURNAL,
3962 EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
3963 EXEC_OUTPUT_KMSG_AND_CONSOLE,
3964 EXEC_OUTPUT_JOURNAL_AND_CONSOLE) ||
3965 IN_SET(c->std_error,
3966 EXEC_OUTPUT_SYSLOG,
3967 EXEC_OUTPUT_KMSG,
3968 EXEC_OUTPUT_JOURNAL,
3969 EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
3970 EXEC_OUTPUT_KMSG_AND_CONSOLE,
3971 EXEC_OUTPUT_JOURNAL_AND_CONSOLE)) {
f8b69d1d 3972
5ce70e5b 3973 _cleanup_free_ char *fac_str = NULL, *lvl_str = NULL;
f8b69d1d 3974
837df140
YW
3975 r = log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
3976 if (r >= 0)
3977 fprintf(f, "%sSyslogFacility: %s\n", prefix, fac_str);
f8b69d1d 3978
837df140
YW
3979 r = log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
3980 if (r >= 0)
3981 fprintf(f, "%sSyslogLevel: %s\n", prefix, lvl_str);
f8b69d1d 3982 }
94f04347 3983
d3070fbd
LP
3984 if (c->log_level_max >= 0) {
3985 _cleanup_free_ char *t = NULL;
3986
3987 (void) log_level_to_string_alloc(c->log_level_max, &t);
3988
3989 fprintf(f, "%sLogLevelMax: %s\n", prefix, strna(t));
3990 }
3991
3992 if (c->n_log_extra_fields > 0) {
3993 size_t j;
3994
3995 for (j = 0; j < c->n_log_extra_fields; j++) {
3996 fprintf(f, "%sLogExtraFields: ", prefix);
3997 fwrite(c->log_extra_fields[j].iov_base,
3998 1, c->log_extra_fields[j].iov_len,
3999 f);
4000 fputc('\n', f);
4001 }
4002 }
4003
07d46372
YW
4004 if (c->secure_bits) {
4005 _cleanup_free_ char *str = NULL;
4006
4007 r = secure_bits_to_string_alloc(c->secure_bits, &str);
4008 if (r >= 0)
4009 fprintf(f, "%sSecure Bits: %s\n", prefix, str);
4010 }
94f04347 4011
a103496c 4012 if (c->capability_bounding_set != CAP_ALL) {
dd1f5bd0 4013 _cleanup_free_ char *str = NULL;
94f04347 4014
dd1f5bd0
YW
4015 r = capability_set_to_string_alloc(c->capability_bounding_set, &str);
4016 if (r >= 0)
4017 fprintf(f, "%sCapabilityBoundingSet: %s\n", prefix, str);
755d4b67
IP
4018 }
4019
4020 if (c->capability_ambient_set != 0) {
dd1f5bd0 4021 _cleanup_free_ char *str = NULL;
755d4b67 4022
dd1f5bd0
YW
4023 r = capability_set_to_string_alloc(c->capability_ambient_set, &str);
4024 if (r >= 0)
4025 fprintf(f, "%sAmbientCapabilities: %s\n", prefix, str);
94f04347
LP
4026 }
4027
4028 if (c->user)
f2d3769a 4029 fprintf(f, "%sUser: %s\n", prefix, c->user);
94f04347 4030 if (c->group)
f2d3769a 4031 fprintf(f, "%sGroup: %s\n", prefix, c->group);
94f04347 4032
29206d46
LP
4033 fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user));
4034
ac6e8be6 4035 if (!strv_isempty(c->supplementary_groups)) {
94f04347 4036 fprintf(f, "%sSupplementaryGroups:", prefix);
15ae422b
LP
4037 strv_fprintf(f, c->supplementary_groups);
4038 fputs("\n", f);
4039 }
94f04347 4040
5b6319dc 4041 if (c->pam_name)
f2d3769a 4042 fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
5b6319dc 4043
2a624c36
AP
4044 if (strv_length(c->read_write_paths) > 0) {
4045 fprintf(f, "%sReadWritePaths:", prefix);
4046 strv_fprintf(f, c->read_write_paths);
15ae422b
LP
4047 fputs("\n", f);
4048 }
4049
2a624c36
AP
4050 if (strv_length(c->read_only_paths) > 0) {
4051 fprintf(f, "%sReadOnlyPaths:", prefix);
4052 strv_fprintf(f, c->read_only_paths);
15ae422b
LP
4053 fputs("\n", f);
4054 }
94f04347 4055
2a624c36
AP
4056 if (strv_length(c->inaccessible_paths) > 0) {
4057 fprintf(f, "%sInaccessiblePaths:", prefix);
4058 strv_fprintf(f, c->inaccessible_paths);
94f04347
LP
4059 fputs("\n", f);
4060 }
2e22afe9 4061
d2d6c096
LP
4062 if (c->n_bind_mounts > 0)
4063 for (i = 0; i < c->n_bind_mounts; i++) {
4064 fprintf(f, "%s%s: %s:%s:%s\n", prefix,
4065 c->bind_mounts[i].read_only ? "BindReadOnlyPaths" : "BindPaths",
4066 c->bind_mounts[i].source,
4067 c->bind_mounts[i].destination,
4068 c->bind_mounts[i].recursive ? "rbind" : "norbind");
4069 }
4070
169c1bda
LP
4071 if (c->utmp_id)
4072 fprintf(f,
4073 "%sUtmpIdentifier: %s\n",
4074 prefix, c->utmp_id);
7b52a628
MS
4075
4076 if (c->selinux_context)
4077 fprintf(f,
5f8640fb
LP
4078 "%sSELinuxContext: %s%s\n",
4079 prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context);
17df7223 4080
80c21aea
WC
4081 if (c->apparmor_profile)
4082 fprintf(f,
4083 "%sAppArmorProfile: %s%s\n",
4084 prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile);
4085
4086 if (c->smack_process_label)
4087 fprintf(f,
4088 "%sSmackProcessLabel: %s%s\n",
4089 prefix, c->smack_process_label_ignore ? "-" : "", c->smack_process_label);
4090
050f7277 4091 if (c->personality != PERSONALITY_INVALID)
ac45f971
LP
4092 fprintf(f,
4093 "%sPersonality: %s\n",
4094 prefix, strna(personality_to_string(c->personality)));
4095
78e864e5
TM
4096 fprintf(f,
4097 "%sLockPersonality: %s\n",
4098 prefix, yes_no(c->lock_personality));
4099
17df7223 4100 if (c->syscall_filter) {
349cc4a5 4101#if HAVE_SECCOMP
17df7223 4102 Iterator j;
8cfa775f 4103 void *id, *val;
17df7223 4104 bool first = true;
351a19b1 4105#endif
17df7223
LP
4106
4107 fprintf(f,
57183d11 4108 "%sSystemCallFilter: ",
17df7223
LP
4109 prefix);
4110
4111 if (!c->syscall_whitelist)
4112 fputc('~', f);
4113
349cc4a5 4114#if HAVE_SECCOMP
8cfa775f 4115 HASHMAP_FOREACH_KEY(val, id, c->syscall_filter, j) {
17df7223 4116 _cleanup_free_ char *name = NULL;
8cfa775f
YW
4117 const char *errno_name = NULL;
4118 int num = PTR_TO_INT(val);
17df7223
LP
4119
4120 if (first)
4121 first = false;
4122 else
4123 fputc(' ', f);
4124
57183d11 4125 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
17df7223 4126 fputs(strna(name), f);
8cfa775f
YW
4127
4128 if (num >= 0) {
4129 errno_name = errno_to_name(num);
4130 if (errno_name)
4131 fprintf(f, ":%s", errno_name);
4132 else
4133 fprintf(f, ":%d", num);
4134 }
17df7223 4135 }
351a19b1 4136#endif
17df7223
LP
4137
4138 fputc('\n', f);
4139 }
4140
57183d11 4141 if (c->syscall_archs) {
349cc4a5 4142#if HAVE_SECCOMP
57183d11
LP
4143 Iterator j;
4144 void *id;
4145#endif
4146
4147 fprintf(f,
4148 "%sSystemCallArchitectures:",
4149 prefix);
4150
349cc4a5 4151#if HAVE_SECCOMP
57183d11
LP
4152 SET_FOREACH(id, c->syscall_archs, j)
4153 fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1)));
4154#endif
4155 fputc('\n', f);
4156 }
4157
add00535
LP
4158 if (exec_context_restrict_namespaces_set(c)) {
4159 _cleanup_free_ char *s = NULL;
4160
4161 r = namespace_flag_to_string_many(c->restrict_namespaces, &s);
4162 if (r >= 0)
4163 fprintf(f, "%sRestrictNamespaces: %s\n",
4164 prefix, s);
4165 }
4166
3df90f24
YW
4167 if (c->syscall_errno > 0) {
4168 const char *errno_name;
4169
4170 fprintf(f, "%sSystemCallErrorNumber: ", prefix);
4171
4172 errno_name = errno_to_name(c->syscall_errno);
4173 if (errno_name)
4174 fprintf(f, "%s\n", errno_name);
4175 else
4176 fprintf(f, "%d\n", c->syscall_errno);
4177 }
eef65bf3
MS
4178
4179 if (c->apparmor_profile)
4180 fprintf(f,
4181 "%sAppArmorProfile: %s%s\n",
4182 prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile);
5cb5a6ff
LP
4183}
4184
a931ad47
LP
4185bool exec_context_maintains_privileges(ExecContext *c) {
4186 assert(c);
4187
61233823 4188 /* Returns true if the process forked off would run under
a931ad47
LP
4189 * an unchanged UID or as root. */
4190
4191 if (!c->user)
4192 return true;
4193
4194 if (streq(c->user, "root") || streq(c->user, "0"))
4195 return true;
4196
4197 return false;
4198}
4199
7f452159
LP
4200int exec_context_get_effective_ioprio(ExecContext *c) {
4201 int p;
4202
4203 assert(c);
4204
4205 if (c->ioprio_set)
4206 return c->ioprio;
4207
4208 p = ioprio_get(IOPRIO_WHO_PROCESS, 0);
4209 if (p < 0)
4210 return IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
4211
4212 return p;
4213}
4214
d3070fbd
LP
4215void exec_context_free_log_extra_fields(ExecContext *c) {
4216 size_t l;
4217
4218 assert(c);
4219
4220 for (l = 0; l < c->n_log_extra_fields; l++)
4221 free(c->log_extra_fields[l].iov_base);
4222 c->log_extra_fields = mfree(c->log_extra_fields);
4223 c->n_log_extra_fields = 0;
4224}
4225
b58b4116 4226void exec_status_start(ExecStatus *s, pid_t pid) {
034c6ed7 4227 assert(s);
5cb5a6ff 4228
b58b4116
LP
4229 zero(*s);
4230 s->pid = pid;
4231 dual_timestamp_get(&s->start_timestamp);
4232}
4233
6ea832a2 4234void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status) {
b58b4116
LP
4235 assert(s);
4236
0b1f4ae6 4237 if (s->pid && s->pid != pid)
b58b4116
LP
4238 zero(*s);
4239
034c6ed7 4240 s->pid = pid;
63983207 4241 dual_timestamp_get(&s->exit_timestamp);
9fb86720 4242
034c6ed7
LP
4243 s->code = code;
4244 s->status = status;
169c1bda 4245
6ea832a2
LP
4246 if (context) {
4247 if (context->utmp_id)
4248 utmp_put_dead_process(context->utmp_id, pid, code, status);
4249
1e22b5cd 4250 exec_context_tty_reset(context, NULL);
6ea832a2 4251 }
9fb86720
LP
4252}
4253
4254void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
4255 char buf[FORMAT_TIMESTAMP_MAX];
4256
4257 assert(s);
4258 assert(f);
4259
9fb86720
LP
4260 if (s->pid <= 0)
4261 return;
4262
4c940960
LP
4263 prefix = strempty(prefix);
4264
9fb86720 4265 fprintf(f,
ccd06097
ZJS
4266 "%sPID: "PID_FMT"\n",
4267 prefix, s->pid);
9fb86720 4268
af9d16e1 4269 if (dual_timestamp_is_set(&s->start_timestamp))
9fb86720
LP
4270 fprintf(f,
4271 "%sStart Timestamp: %s\n",
63983207 4272 prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
9fb86720 4273
af9d16e1 4274 if (dual_timestamp_is_set(&s->exit_timestamp))
9fb86720
LP
4275 fprintf(f,
4276 "%sExit Timestamp: %s\n"
4277 "%sExit Code: %s\n"
4278 "%sExit Status: %i\n",
63983207 4279 prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
9fb86720
LP
4280 prefix, sigchld_code_to_string(s->code),
4281 prefix, s->status);
5cb5a6ff 4282}
44d8db9e 4283
9e2f7c11 4284char *exec_command_line(char **argv) {
44d8db9e
LP
4285 size_t k;
4286 char *n, *p, **a;
4287 bool first = true;
4288
9e2f7c11 4289 assert(argv);
44d8db9e 4290
9164977d 4291 k = 1;
9e2f7c11 4292 STRV_FOREACH(a, argv)
44d8db9e
LP
4293 k += strlen(*a)+3;
4294
5cd9cd35
LP
4295 n = new(char, k);
4296 if (!n)
44d8db9e
LP
4297 return NULL;
4298
4299 p = n;
9e2f7c11 4300 STRV_FOREACH(a, argv) {
44d8db9e
LP
4301
4302 if (!first)
4303 *(p++) = ' ';
4304 else
4305 first = false;
4306
4307 if (strpbrk(*a, WHITESPACE)) {
4308 *(p++) = '\'';
4309 p = stpcpy(p, *a);
4310 *(p++) = '\'';
4311 } else
4312 p = stpcpy(p, *a);
4313
4314 }
4315
9164977d
LP
4316 *p = 0;
4317
44d8db9e
LP
4318 /* FIXME: this doesn't really handle arguments that have
4319 * spaces and ticks in them */
4320
4321 return n;
4322}
4323
4324void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
e1d75803 4325 _cleanup_free_ char *cmd = NULL;
4c940960 4326 const char *prefix2;
44d8db9e
LP
4327
4328 assert(c);
4329 assert(f);
4330
4c940960 4331 prefix = strempty(prefix);
63c372cb 4332 prefix2 = strjoina(prefix, "\t");
44d8db9e 4333
9e2f7c11 4334 cmd = exec_command_line(c->argv);
44d8db9e
LP
4335 fprintf(f,
4336 "%sCommand Line: %s\n",
4337 prefix, cmd ? cmd : strerror(ENOMEM));
4338
9fb86720 4339 exec_status_dump(&c->exec_status, f, prefix2);
44d8db9e
LP
4340}
4341
4342void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
4343 assert(f);
4344
4c940960 4345 prefix = strempty(prefix);
44d8db9e
LP
4346
4347 LIST_FOREACH(command, c, c)
4348 exec_command_dump(c, f, prefix);
4349}
94f04347 4350
a6a80b4f
LP
4351void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
4352 ExecCommand *end;
4353
4354 assert(l);
4355 assert(e);
4356
4357 if (*l) {
35b8ca3a 4358 /* It's kind of important, that we keep the order here */
71fda00f
LP
4359 LIST_FIND_TAIL(command, *l, end);
4360 LIST_INSERT_AFTER(command, *l, end, e);
a6a80b4f
LP
4361 } else
4362 *l = e;
4363}
4364
26fd040d
LP
4365int exec_command_set(ExecCommand *c, const char *path, ...) {
4366 va_list ap;
4367 char **l, *p;
4368
4369 assert(c);
4370 assert(path);
4371
4372 va_start(ap, path);
4373 l = strv_new_ap(path, ap);
4374 va_end(ap);
4375
4376 if (!l)
4377 return -ENOMEM;
4378
250a918d
LP
4379 p = strdup(path);
4380 if (!p) {
26fd040d
LP
4381 strv_free(l);
4382 return -ENOMEM;
4383 }
4384
4385 free(c->path);
4386 c->path = p;
4387
4388 strv_free(c->argv);
4389 c->argv = l;
4390
4391 return 0;
4392}
4393
86b23b07 4394int exec_command_append(ExecCommand *c, const char *path, ...) {
e63ff941 4395 _cleanup_strv_free_ char **l = NULL;
86b23b07 4396 va_list ap;
86b23b07
JS
4397 int r;
4398
4399 assert(c);
4400 assert(path);
4401
4402 va_start(ap, path);
4403 l = strv_new_ap(path, ap);
4404 va_end(ap);
4405
4406 if (!l)
4407 return -ENOMEM;
4408
e287086b 4409 r = strv_extend_strv(&c->argv, l, false);
e63ff941 4410 if (r < 0)
86b23b07 4411 return r;
86b23b07
JS
4412
4413 return 0;
4414}
4415
4416
613b411c
LP
4417static int exec_runtime_allocate(ExecRuntime **rt) {
4418
4419 if (*rt)
4420 return 0;
4421
4422 *rt = new0(ExecRuntime, 1);
f146f5e1 4423 if (!*rt)
613b411c
LP
4424 return -ENOMEM;
4425
4426 (*rt)->n_ref = 1;
4427 (*rt)->netns_storage_socket[0] = (*rt)->netns_storage_socket[1] = -1;
4428
4429 return 0;
4430}
4431
4432int exec_runtime_make(ExecRuntime **rt, ExecContext *c, const char *id) {
4433 int r;
4434
4435 assert(rt);
4436 assert(c);
4437 assert(id);
4438
4439 if (*rt)
4440 return 1;
4441
4442 if (!c->private_network && !c->private_tmp)
4443 return 0;
4444
4445 r = exec_runtime_allocate(rt);
4446 if (r < 0)
4447 return r;
4448
4449 if (c->private_network && (*rt)->netns_storage_socket[0] < 0) {
33df919d 4450 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, (*rt)->netns_storage_socket) < 0)
613b411c
LP
4451 return -errno;
4452 }
4453
4454 if (c->private_tmp && !(*rt)->tmp_dir) {
4455 r = setup_tmp_dirs(id, &(*rt)->tmp_dir, &(*rt)->var_tmp_dir);
4456 if (r < 0)
4457 return r;
4458 }
4459
4460 return 1;
4461}
4462
4463ExecRuntime *exec_runtime_ref(ExecRuntime *r) {
4464 assert(r);
4465 assert(r->n_ref > 0);
4466
4467 r->n_ref++;
4468 return r;
4469}
4470
4471ExecRuntime *exec_runtime_unref(ExecRuntime *r) {
4472
4473 if (!r)
4474 return NULL;
4475
4476 assert(r->n_ref > 0);
4477
4478 r->n_ref--;
f2341e0a
LP
4479 if (r->n_ref > 0)
4480 return NULL;
4481
4482 free(r->tmp_dir);
4483 free(r->var_tmp_dir);
4484 safe_close_pair(r->netns_storage_socket);
6b430fdb 4485 return mfree(r);
613b411c
LP
4486}
4487
f2341e0a 4488int exec_runtime_serialize(Unit *u, ExecRuntime *rt, FILE *f, FDSet *fds) {
613b411c
LP
4489 assert(u);
4490 assert(f);
4491 assert(fds);
4492
4493 if (!rt)
4494 return 0;
4495
4496 if (rt->tmp_dir)
4497 unit_serialize_item(u, f, "tmp-dir", rt->tmp_dir);
4498
4499 if (rt->var_tmp_dir)
4500 unit_serialize_item(u, f, "var-tmp-dir", rt->var_tmp_dir);
4501
4502 if (rt->netns_storage_socket[0] >= 0) {
4503 int copy;
4504
4505 copy = fdset_put_dup(fds, rt->netns_storage_socket[0]);
4506 if (copy < 0)
4507 return copy;
4508
4509 unit_serialize_item_format(u, f, "netns-socket-0", "%i", copy);
4510 }
4511
4512 if (rt->netns_storage_socket[1] >= 0) {
4513 int copy;
4514
4515 copy = fdset_put_dup(fds, rt->netns_storage_socket[1]);
4516 if (copy < 0)
4517 return copy;
4518
4519 unit_serialize_item_format(u, f, "netns-socket-1", "%i", copy);
4520 }
4521
4522 return 0;
4523}
4524
f2341e0a 4525int exec_runtime_deserialize_item(Unit *u, ExecRuntime **rt, const char *key, const char *value, FDSet *fds) {
613b411c
LP
4526 int r;
4527
4528 assert(rt);
4529 assert(key);
4530 assert(value);
4531
4532 if (streq(key, "tmp-dir")) {
4533 char *copy;
4534
4535 r = exec_runtime_allocate(rt);
4536 if (r < 0)
f2341e0a 4537 return log_oom();
613b411c
LP
4538
4539 copy = strdup(value);
4540 if (!copy)
4541 return log_oom();
4542
4543 free((*rt)->tmp_dir);
4544 (*rt)->tmp_dir = copy;
4545
4546 } else if (streq(key, "var-tmp-dir")) {
4547 char *copy;
4548
4549 r = exec_runtime_allocate(rt);
4550 if (r < 0)
f2341e0a 4551 return log_oom();
613b411c
LP
4552
4553 copy = strdup(value);
4554 if (!copy)
4555 return log_oom();
4556
4557 free((*rt)->var_tmp_dir);
4558 (*rt)->var_tmp_dir = copy;
4559
4560 } else if (streq(key, "netns-socket-0")) {
4561 int fd;
4562
4563 r = exec_runtime_allocate(rt);
4564 if (r < 0)
f2341e0a 4565 return log_oom();
613b411c
LP
4566
4567 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
f2341e0a 4568 log_unit_debug(u, "Failed to parse netns socket value: %s", value);
613b411c 4569 else {
03e334a1 4570 safe_close((*rt)->netns_storage_socket[0]);
613b411c
LP
4571 (*rt)->netns_storage_socket[0] = fdset_remove(fds, fd);
4572 }
4573 } else if (streq(key, "netns-socket-1")) {
4574 int fd;
4575
4576 r = exec_runtime_allocate(rt);
4577 if (r < 0)
f2341e0a 4578 return log_oom();
613b411c
LP
4579
4580 if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
f2341e0a 4581 log_unit_debug(u, "Failed to parse netns socket value: %s", value);
613b411c 4582 else {
03e334a1 4583 safe_close((*rt)->netns_storage_socket[1]);
613b411c
LP
4584 (*rt)->netns_storage_socket[1] = fdset_remove(fds, fd);
4585 }
4586 } else
4587 return 0;
4588
4589 return 1;
4590}
4591
4592static void *remove_tmpdir_thread(void *p) {
4593 _cleanup_free_ char *path = p;
4594
c6878637 4595 (void) rm_rf(path, REMOVE_ROOT|REMOVE_PHYSICAL);
613b411c
LP
4596 return NULL;
4597}
4598
4599void exec_runtime_destroy(ExecRuntime *rt) {
98b47d54
LP
4600 int r;
4601
613b411c
LP
4602 if (!rt)
4603 return;
4604
4605 /* If there are multiple users of this, let's leave the stuff around */
4606 if (rt->n_ref > 1)
4607 return;
4608
4609 if (rt->tmp_dir) {
4610 log_debug("Spawning thread to nuke %s", rt->tmp_dir);
98b47d54
LP
4611
4612 r = asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
4613 if (r < 0) {
da927ba9 4614 log_warning_errno(r, "Failed to nuke %s: %m", rt->tmp_dir);
98b47d54
LP
4615 free(rt->tmp_dir);
4616 }
4617
613b411c
LP
4618 rt->tmp_dir = NULL;
4619 }
4620
4621 if (rt->var_tmp_dir) {
4622 log_debug("Spawning thread to nuke %s", rt->var_tmp_dir);
98b47d54
LP
4623
4624 r = asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
4625 if (r < 0) {
da927ba9 4626 log_warning_errno(r, "Failed to nuke %s: %m", rt->var_tmp_dir);
98b47d54
LP
4627 free(rt->var_tmp_dir);
4628 }
4629
613b411c
LP
4630 rt->var_tmp_dir = NULL;
4631 }
4632
3d94f76c 4633 safe_close_pair(rt->netns_storage_socket);
613b411c
LP
4634}
4635
80876c20
LP
4636static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
4637 [EXEC_INPUT_NULL] = "null",
4638 [EXEC_INPUT_TTY] = "tty",
4639 [EXEC_INPUT_TTY_FORCE] = "tty-force",
4f2d528d 4640 [EXEC_INPUT_TTY_FAIL] = "tty-fail",
52c239d7
LB
4641 [EXEC_INPUT_SOCKET] = "socket",
4642 [EXEC_INPUT_NAMED_FD] = "fd",
08f3be7a 4643 [EXEC_INPUT_DATA] = "data",
80876c20
LP
4644};
4645
8a0867d6
LP
4646DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
4647
94f04347 4648static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
80876c20 4649 [EXEC_OUTPUT_INHERIT] = "inherit",
94f04347 4650 [EXEC_OUTPUT_NULL] = "null",
80876c20 4651 [EXEC_OUTPUT_TTY] = "tty",
94f04347 4652 [EXEC_OUTPUT_SYSLOG] = "syslog",
28dbc1e8 4653 [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
9a6bca7a 4654 [EXEC_OUTPUT_KMSG] = "kmsg",
28dbc1e8 4655 [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
706343f4
LP
4656 [EXEC_OUTPUT_JOURNAL] = "journal",
4657 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
52c239d7
LB
4658 [EXEC_OUTPUT_SOCKET] = "socket",
4659 [EXEC_OUTPUT_NAMED_FD] = "fd",
94f04347
LP
4660};
4661
4662DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
023a4f67
LP
4663
4664static const char* const exec_utmp_mode_table[_EXEC_UTMP_MODE_MAX] = {
4665 [EXEC_UTMP_INIT] = "init",
4666 [EXEC_UTMP_LOGIN] = "login",
4667 [EXEC_UTMP_USER] = "user",
4668};
4669
4670DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode, ExecUtmpMode);
53f47dfc
YW
4671
4672static const char* const exec_preserve_mode_table[_EXEC_PRESERVE_MODE_MAX] = {
4673 [EXEC_PRESERVE_NO] = "no",
4674 [EXEC_PRESERVE_YES] = "yes",
4675 [EXEC_PRESERVE_RESTART] = "restart",
4676};
4677
4678DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode, ExecPreserveMode, EXEC_PRESERVE_YES);
3536f49e 4679
72fd1768 4680static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
3536f49e
YW
4681 [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
4682 [EXEC_DIRECTORY_STATE] = "StateDirectory",
4683 [EXEC_DIRECTORY_CACHE] = "CacheDirectory",
4684 [EXEC_DIRECTORY_LOGS] = "LogsDirectory",
4685 [EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
4686};
4687
4688DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);
b1edf445
LP
4689
4690static const char* const exec_keyring_mode_table[_EXEC_KEYRING_MODE_MAX] = {
4691 [EXEC_KEYRING_INHERIT] = "inherit",
4692 [EXEC_KEYRING_PRIVATE] = "private",
4693 [EXEC_KEYRING_SHARED] = "shared",
4694};
4695
4696DEFINE_STRING_TABLE_LOOKUP(exec_keyring_mode, ExecKeyringMode);