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