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