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