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