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