]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/execute.c
systemctl: introduce "systemctl man" to show man page for unit
[thirdparty/systemd.git] / src / core / execute.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5cb5a6ff 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
5cb5a6ff 22#include <assert.h>
034c6ed7
LP
23#include <dirent.h>
24#include <errno.h>
25#include <fcntl.h>
26#include <unistd.h>
44d8db9e 27#include <string.h>
309bff19 28#include <signal.h>
071830ff
LP
29#include <sys/socket.h>
30#include <sys/un.h>
94f04347 31#include <sys/prctl.h>
66ee3769 32#include <linux/sched.h>
451a074f
LP
33#include <sys/types.h>
34#include <sys/stat.h>
81a2b7ce
LP
35#include <grp.h>
36#include <pwd.h>
15ae422b 37#include <sys/mount.h>
25e870b5 38#include <linux/fs.h>
dd6c17b1 39#include <linux/oom.h>
f2b68789 40#include <sys/poll.h>
5cb5a6ff 41
5b6319dc
LP
42#ifdef HAVE_PAM
43#include <security/pam_appl.h>
44#endif
45
5cb5a6ff
LP
46#include "execute.h"
47#include "strv.h"
48#include "macro.h"
d7832d2c 49#include "capability.h"
5cb5a6ff 50#include "util.h"
acbb0225 51#include "log.h"
9eba9da4 52#include "ioprio.h"
94f04347 53#include "securebits.h"
8e274523 54#include "cgroup.h"
15ae422b 55#include "namespace.h"
df1f0afe 56#include "tcpwrap.h"
d06dacd0 57#include "exit-status.h"
dd6c17b1 58#include "missing.h"
169c1bda 59#include "utmp-wtmp.h"
f6a6225e 60#include "def.h"
ff01d048 61#include "loopback-setup.h"
9eb977db 62#include "path-util.h"
5cb5a6ff 63
e056b01d 64#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
e6a26745 65
02a51aba
LP
66/* This assumes there is a 'tty' group */
67#define TTY_MODE 0620
68
034c6ed7
LP
69static int shift_fds(int fds[], unsigned n_fds) {
70 int start, restart_from;
71
72 if (n_fds <= 0)
73 return 0;
74
a0d40ac5
LP
75 /* Modifies the fds array! (sorts it) */
76
034c6ed7
LP
77 assert(fds);
78
79 start = 0;
80 for (;;) {
81 int i;
82
83 restart_from = -1;
84
85 for (i = start; i < (int) n_fds; i++) {
86 int nfd;
87
88 /* Already at right index? */
89 if (fds[i] == i+3)
90 continue;
91
92 if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0)
93 return -errno;
94
e1f5e051 95 close_nointr_nofail(fds[i]);
034c6ed7
LP
96 fds[i] = nfd;
97
98 /* Hmm, the fd we wanted isn't free? Then
99 * let's remember that and try again from here*/
100 if (nfd != i+3 && restart_from < 0)
101 restart_from = i;
102 }
103
104 if (restart_from < 0)
105 break;
106
107 start = restart_from;
108 }
109
110 return 0;
111}
112
c2748801 113static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
47a71eed 114 unsigned i;
e2c76839 115 int r;
47a71eed
LP
116
117 if (n_fds <= 0)
118 return 0;
119
120 assert(fds);
121
451a074f 122 /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
47a71eed
LP
123
124 for (i = 0; i < n_fds; i++) {
47a71eed 125
e2c76839
LP
126 if ((r = fd_nonblock(fds[i], nonblock)) < 0)
127 return r;
47a71eed 128
451a074f
LP
129 /* We unconditionally drop FD_CLOEXEC from the fds,
130 * since after all we want to pass these fds to our
131 * children */
47a71eed 132
e2c76839
LP
133 if ((r = fd_cloexec(fds[i], false)) < 0)
134 return r;
47a71eed
LP
135 }
136
137 return 0;
138}
139
80876c20
LP
140static const char *tty_path(const ExecContext *context) {
141 assert(context);
142
143 if (context->tty_path)
144 return context->tty_path;
145
146 return "/dev/console";
147}
148
6ea832a2
LP
149void exec_context_tty_reset(const ExecContext *context) {
150 assert(context);
151
152 if (context->tty_vhangup)
153 terminal_vhangup(tty_path(context));
154
155 if (context->tty_reset)
156 reset_terminal(tty_path(context));
157
158 if (context->tty_vt_disallocate && context->tty_path)
159 vt_disallocate(context->tty_path);
160}
161
80876c20
LP
162static int open_null_as(int flags, int nfd) {
163 int fd, r;
071830ff 164
80876c20 165 assert(nfd >= 0);
071830ff 166
80876c20 167 if ((fd = open("/dev/null", flags|O_NOCTTY)) < 0)
071830ff
LP
168 return -errno;
169
80876c20
LP
170 if (fd != nfd) {
171 r = dup2(fd, nfd) < 0 ? -errno : nfd;
e1f5e051 172 close_nointr_nofail(fd);
80876c20
LP
173 } else
174 r = nfd;
071830ff 175
80876c20 176 return r;
071830ff
LP
177}
178
80876c20
LP
179static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, int nfd) {
180 int fd, r;
54fe0cdb 181 union sockaddr_union sa;
071830ff
LP
182
183 assert(context);
80876c20
LP
184 assert(output < _EXEC_OUTPUT_MAX);
185 assert(ident);
186 assert(nfd >= 0);
071830ff 187
54fe0cdb
LP
188 fd = socket(AF_UNIX, SOCK_STREAM, 0);
189 if (fd < 0)
80876c20 190 return -errno;
071830ff 191
80876c20 192 zero(sa);
54fe0cdb
LP
193 sa.un.sun_family = AF_UNIX;
194 strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
071830ff 195
54fe0cdb
LP
196 r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
197 if (r < 0) {
80876c20
LP
198 close_nointr_nofail(fd);
199 return -errno;
200 }
071830ff 201
80876c20
LP
202 if (shutdown(fd, SHUT_RD) < 0) {
203 close_nointr_nofail(fd);
204 return -errno;
205 }
071830ff 206
80876c20
LP
207 dprintf(fd,
208 "%s\n"
209 "%i\n"
54fe0cdb
LP
210 "%i\n"
211 "%i\n"
212 "%i\n"
4f4a1dbf 213 "%i\n",
4f4a1dbf 214 context->syslog_identifier ? context->syslog_identifier : ident,
54fe0cdb
LP
215 context->syslog_priority,
216 !!context->syslog_level_prefix,
217 output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
218 output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
706343f4 219 output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || output == EXEC_OUTPUT_KMSG_AND_CONSOLE || output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE);
80876c20
LP
220
221 if (fd != nfd) {
222 r = dup2(fd, nfd) < 0 ? -errno : nfd;
e1f5e051 223 close_nointr_nofail(fd);
80876c20
LP
224 } else
225 r = nfd;
071830ff 226
80876c20
LP
227 return r;
228}
229static int open_terminal_as(const char *path, mode_t mode, int nfd) {
230 int fd, r;
071830ff 231
80876c20
LP
232 assert(path);
233 assert(nfd >= 0);
071830ff 234
80876c20
LP
235 if ((fd = open_terminal(path, mode | O_NOCTTY)) < 0)
236 return fd;
071830ff 237
80876c20
LP
238 if (fd != nfd) {
239 r = dup2(fd, nfd) < 0 ? -errno : nfd;
240 close_nointr_nofail(fd);
241 } else
242 r = nfd;
071830ff 243
80876c20
LP
244 return r;
245}
071830ff 246
80876c20
LP
247static bool is_terminal_input(ExecInput i) {
248 return
249 i == EXEC_INPUT_TTY ||
250 i == EXEC_INPUT_TTY_FORCE ||
251 i == EXEC_INPUT_TTY_FAIL;
252}
071830ff 253
1e3ad081
LP
254static int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
255
256 if (is_terminal_input(std_input) && !apply_tty_stdin)
257 return EXEC_INPUT_NULL;
071830ff 258
03fd9c49 259 if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
4f2d528d
LP
260 return EXEC_INPUT_NULL;
261
03fd9c49 262 return std_input;
4f2d528d
LP
263}
264
03fd9c49 265static int fixup_output(ExecOutput std_output, int socket_fd) {
4f2d528d 266
03fd9c49 267 if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
4f2d528d
LP
268 return EXEC_OUTPUT_INHERIT;
269
03fd9c49 270 return std_output;
4f2d528d
LP
271}
272
1e3ad081 273static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
4f2d528d
LP
274 ExecInput i;
275
276 assert(context);
277
1e3ad081 278 i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
4f2d528d
LP
279
280 switch (i) {
071830ff 281
80876c20
LP
282 case EXEC_INPUT_NULL:
283 return open_null_as(O_RDONLY, STDIN_FILENO);
284
285 case EXEC_INPUT_TTY:
286 case EXEC_INPUT_TTY_FORCE:
287 case EXEC_INPUT_TTY_FAIL: {
288 int fd, r;
071830ff 289
80876c20
LP
290 if ((fd = acquire_terminal(
291 tty_path(context),
4f2d528d 292 i == EXEC_INPUT_TTY_FAIL,
21de3988
LP
293 i == EXEC_INPUT_TTY_FORCE,
294 false)) < 0)
80876c20
LP
295 return fd;
296
297 if (fd != STDIN_FILENO) {
298 r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
071830ff 299 close_nointr_nofail(fd);
80876c20
LP
300 } else
301 r = STDIN_FILENO;
302
303 return r;
304 }
305
4f2d528d
LP
306 case EXEC_INPUT_SOCKET:
307 return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
308
80876c20
LP
309 default:
310 assert_not_reached("Unknown input type");
311 }
312}
313
1e3ad081 314static int setup_output(const ExecContext *context, int socket_fd, const char *ident, bool apply_tty_stdin) {
4f2d528d
LP
315 ExecOutput o;
316 ExecInput i;
317
80876c20
LP
318 assert(context);
319 assert(ident);
320
1e3ad081 321 i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
03fd9c49 322 o = fixup_output(context->std_output, socket_fd);
4f2d528d 323
80876c20
LP
324 /* This expects the input is already set up */
325
4f2d528d 326 switch (o) {
071830ff 327
80876c20
LP
328 case EXEC_OUTPUT_INHERIT:
329
21d21ea4
LP
330 /* If input got downgraded, inherit the original value */
331 if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
332 return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
333
acb591e4 334 /* If the input is connected to anything that's not a /dev/null, inherit that... */
ff876e28 335 if (i != EXEC_INPUT_NULL)
80876c20 336 return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
071830ff 337
acb591e4
LP
338 /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
339 if (getppid() != 1)
340 return STDOUT_FILENO;
ff876e28 341
acb591e4
LP
342 /* We need to open /dev/null here anew, to get the
343 * right access mode. So we fall through */
80876c20
LP
344
345 case EXEC_OUTPUT_NULL:
346 return open_null_as(O_WRONLY, STDOUT_FILENO);
347
4f2d528d
LP
348 case EXEC_OUTPUT_TTY:
349 if (is_terminal_input(i))
80876c20
LP
350 return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
351
352 /* We don't reset the terminal if this is just about output */
353 return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
94f04347 354
80876c20 355 case EXEC_OUTPUT_SYSLOG:
28dbc1e8 356 case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
9a6bca7a 357 case EXEC_OUTPUT_KMSG:
28dbc1e8 358 case EXEC_OUTPUT_KMSG_AND_CONSOLE:
706343f4
LP
359 case EXEC_OUTPUT_JOURNAL:
360 case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
4f2d528d
LP
361 return connect_logger_as(context, o, ident, STDOUT_FILENO);
362
363 case EXEC_OUTPUT_SOCKET:
364 assert(socket_fd >= 0);
365 return dup2(socket_fd, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
80876c20 366
94f04347
LP
367 default:
368 assert_not_reached("Unknown output type");
071830ff 369 }
94f04347
LP
370}
371
1e3ad081 372static int setup_error(const ExecContext *context, int socket_fd, const char *ident, bool apply_tty_stdin) {
4f2d528d
LP
373 ExecOutput o, e;
374 ExecInput i;
375
94f04347 376 assert(context);
02a51aba 377 assert(ident);
071830ff 378
1e3ad081 379 i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
03fd9c49
LP
380 o = fixup_output(context->std_output, socket_fd);
381 e = fixup_output(context->std_error, socket_fd);
4f2d528d 382
80876c20 383 /* This expects the input and output are already set up */
94f04347 384
80876c20
LP
385 /* Don't change the stderr file descriptor if we inherit all
386 * the way and are not on a tty */
4f2d528d
LP
387 if (e == EXEC_OUTPUT_INHERIT &&
388 o == EXEC_OUTPUT_INHERIT &&
acb591e4 389 i == EXEC_INPUT_NULL &&
21d21ea4 390 !is_terminal_input(context->std_input) &&
dec5d552 391 getppid () != 1)
80876c20 392 return STDERR_FILENO;
94f04347 393
21d21ea4 394 /* Duplicate from stdout if possible */
4f2d528d 395 if (e == o || e == EXEC_OUTPUT_INHERIT)
80876c20 396 return dup2(STDOUT_FILENO, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
94f04347 397
4f2d528d 398 switch (e) {
80876c20
LP
399
400 case EXEC_OUTPUT_NULL:
401 return open_null_as(O_WRONLY, STDERR_FILENO);
402
403 case EXEC_OUTPUT_TTY:
4f2d528d 404 if (is_terminal_input(i))
80876c20
LP
405 return dup2(STDIN_FILENO, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
406
407 /* We don't reset the terminal if this is just about output */
408 return open_terminal_as(tty_path(context), O_WRONLY, STDERR_FILENO);
409
410 case EXEC_OUTPUT_SYSLOG:
28dbc1e8 411 case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
9a6bca7a 412 case EXEC_OUTPUT_KMSG:
28dbc1e8 413 case EXEC_OUTPUT_KMSG_AND_CONSOLE:
706343f4
LP
414 case EXEC_OUTPUT_JOURNAL:
415 case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
4f2d528d
LP
416 return connect_logger_as(context, e, ident, STDERR_FILENO);
417
418 case EXEC_OUTPUT_SOCKET:
419 assert(socket_fd >= 0);
420 return dup2(socket_fd, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
94f04347
LP
421
422 default:
80876c20 423 assert_not_reached("Unknown error type");
94f04347 424 }
071830ff
LP
425}
426
02a51aba
LP
427static int chown_terminal(int fd, uid_t uid) {
428 struct stat st;
429
430 assert(fd >= 0);
02a51aba
LP
431
432 /* This might fail. What matters are the results. */
bab45044
LP
433 (void) fchown(fd, uid, -1);
434 (void) fchmod(fd, TTY_MODE);
02a51aba
LP
435
436 if (fstat(fd, &st) < 0)
437 return -errno;
438
d8b4e2e9 439 if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
02a51aba
LP
440 return -EPERM;
441
442 return 0;
443}
444
80876c20
LP
445static int setup_confirm_stdio(const ExecContext *context,
446 int *_saved_stdin,
447 int *_saved_stdout) {
448 int fd = -1, saved_stdin, saved_stdout = -1, r;
449
450 assert(context);
451 assert(_saved_stdin);
452 assert(_saved_stdout);
453
454 /* This returns positive EXIT_xxx return values instead of
455 * negative errno style values! */
456
457 if ((saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3)) < 0)
458 return EXIT_STDIN;
459
460 if ((saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3)) < 0) {
461 r = EXIT_STDOUT;
462 goto fail;
463 }
464
465 if ((fd = acquire_terminal(
466 tty_path(context),
467 context->std_input == EXEC_INPUT_TTY_FAIL,
21de3988
LP
468 context->std_input == EXEC_INPUT_TTY_FORCE,
469 false)) < 0) {
80876c20
LP
470 r = EXIT_STDIN;
471 goto fail;
472 }
473
02a51aba
LP
474 if (chown_terminal(fd, getuid()) < 0) {
475 r = EXIT_STDIN;
476 goto fail;
477 }
478
80876c20
LP
479 if (dup2(fd, STDIN_FILENO) < 0) {
480 r = EXIT_STDIN;
481 goto fail;
482 }
483
484 if (dup2(fd, STDOUT_FILENO) < 0) {
485 r = EXIT_STDOUT;
486 goto fail;
487 }
488
489 if (fd >= 2)
490 close_nointr_nofail(fd);
491
492 *_saved_stdin = saved_stdin;
493 *_saved_stdout = saved_stdout;
494
495 return 0;
496
497fail:
498 if (saved_stdout >= 0)
499 close_nointr_nofail(saved_stdout);
500
501 if (saved_stdin >= 0)
502 close_nointr_nofail(saved_stdin);
503
504 if (fd >= 0)
505 close_nointr_nofail(fd);
506
507 return r;
508}
509
2608882f 510static int restore_confirm_stdio(const ExecContext *context,
80876c20
LP
511 int *saved_stdin,
512 int *saved_stdout,
513 bool *keep_stdin,
514 bool *keep_stdout) {
515
516 assert(context);
517 assert(saved_stdin);
518 assert(*saved_stdin >= 0);
519 assert(saved_stdout);
520 assert(*saved_stdout >= 0);
521
522 /* This returns positive EXIT_xxx return values instead of
523 * negative errno style values! */
524
525 if (is_terminal_input(context->std_input)) {
526
527 /* The service wants terminal input. */
528
529 *keep_stdin = true;
530 *keep_stdout =
531 context->std_output == EXEC_OUTPUT_INHERIT ||
532 context->std_output == EXEC_OUTPUT_TTY;
533
534 } else {
535 /* If the service doesn't want a controlling terminal,
536 * then we need to get rid entirely of what we have
537 * already. */
538
539 if (release_terminal() < 0)
540 return EXIT_STDIN;
541
542 if (dup2(*saved_stdin, STDIN_FILENO) < 0)
543 return EXIT_STDIN;
544
545 if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
546 return EXIT_STDOUT;
547
548 *keep_stdout = *keep_stdin = false;
549 }
550
551 return 0;
552}
553
81a2b7ce
LP
554static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
555 bool keep_groups = false;
556 int r;
557
558 assert(context);
559
35b8ca3a 560 /* Lookup and set GID and supplementary group list. Here too
81a2b7ce
LP
561 * we avoid NSS lookups for gid=0. */
562
563 if (context->group || username) {
564
4b67834e
LP
565 if (context->group) {
566 const char *g = context->group;
567
568 if ((r = get_group_creds(&g, &gid)) < 0)
81a2b7ce 569 return r;
4b67834e 570 }
81a2b7ce
LP
571
572 /* First step, initialize groups from /etc/groups */
573 if (username && gid != 0) {
574 if (initgroups(username, gid) < 0)
575 return -errno;
576
577 keep_groups = true;
578 }
579
580 /* Second step, set our gids */
581 if (setresgid(gid, gid, gid) < 0)
582 return -errno;
583 }
584
585 if (context->supplementary_groups) {
586 int ngroups_max, k;
587 gid_t *gids;
588 char **i;
589
590 /* Final step, initialize any manually set supplementary groups */
da19d5c1 591 assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
81a2b7ce
LP
592
593 if (!(gids = new(gid_t, ngroups_max)))
594 return -ENOMEM;
595
596 if (keep_groups) {
597 if ((k = getgroups(ngroups_max, gids)) < 0) {
598 free(gids);
599 return -errno;
600 }
601 } else
602 k = 0;
603
604 STRV_FOREACH(i, context->supplementary_groups) {
4b67834e 605 const char *g;
81a2b7ce
LP
606
607 if (k >= ngroups_max) {
608 free(gids);
609 return -E2BIG;
610 }
611
4b67834e
LP
612 g = *i;
613 r = get_group_creds(&g, gids+k);
614 if (r < 0) {
81a2b7ce
LP
615 free(gids);
616 return r;
617 }
618
619 k++;
620 }
621
622 if (setgroups(k, gids) < 0) {
623 free(gids);
624 return -errno;
625 }
626
627 free(gids);
628 }
629
630 return 0;
631}
632
633static int enforce_user(const ExecContext *context, uid_t uid) {
634 int r;
635 assert(context);
636
637 /* Sets (but doesn't lookup) the uid and make sure we keep the
638 * capabilities while doing so. */
639
640 if (context->capabilities) {
641 cap_t d;
642 static const cap_value_t bits[] = {
643 CAP_SETUID, /* Necessary so that we can run setresuid() below */
644 CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
645 };
646
647 /* First step: If we need to keep capabilities but
648 * drop privileges we need to make sure we keep our
35b8ca3a 649 * caps, whiel we drop privileges. */
693ced48
LP
650 if (uid != 0) {
651 int sb = context->secure_bits|SECURE_KEEP_CAPS;
652
653 if (prctl(PR_GET_SECUREBITS) != sb)
654 if (prctl(PR_SET_SECUREBITS, sb) < 0)
655 return -errno;
656 }
81a2b7ce 657
35b8ca3a 658 /* Second step: set the capabilities. This will reduce
81a2b7ce
LP
659 * the capabilities to the minimum we need. */
660
661 if (!(d = cap_dup(context->capabilities)))
662 return -errno;
663
664 if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
665 cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0) {
666 r = -errno;
667 cap_free(d);
668 return r;
669 }
670
671 if (cap_set_proc(d) < 0) {
672 r = -errno;
673 cap_free(d);
674 return r;
675 }
676
677 cap_free(d);
678 }
679
680 /* Third step: actually set the uids */
681 if (setresuid(uid, uid, uid) < 0)
682 return -errno;
683
684 /* At this point we should have all necessary capabilities but
685 are otherwise a normal user. However, the caps might got
686 corrupted due to the setresuid() so we need clean them up
687 later. This is done outside of this call. */
688
689 return 0;
690}
691
5b6319dc
LP
692#ifdef HAVE_PAM
693
694static int null_conv(
695 int num_msg,
696 const struct pam_message **msg,
697 struct pam_response **resp,
698 void *appdata_ptr) {
699
700 /* We don't support conversations */
701
702 return PAM_CONV_ERR;
703}
704
705static int setup_pam(
706 const char *name,
707 const char *user,
940c5210 708 uid_t uid,
5b6319dc
LP
709 const char *tty,
710 char ***pam_env,
711 int fds[], unsigned n_fds) {
712
713 static const struct pam_conv conv = {
714 .conv = null_conv,
715 .appdata_ptr = NULL
716 };
717
718 pam_handle_t *handle = NULL;
719 sigset_t ss, old_ss;
720 int pam_code = PAM_SUCCESS;
9ba35398 721 int err;
5b6319dc
LP
722 char **e = NULL;
723 bool close_session = false;
724 pid_t pam_pid = 0, parent_pid;
725
726 assert(name);
727 assert(user);
728 assert(pam_env);
729
730 /* We set up PAM in the parent process, then fork. The child
35b8ca3a 731 * will then stay around until killed via PR_GET_PDEATHSIG or
5b6319dc
LP
732 * systemd via the cgroup logic. It will then remove the PAM
733 * session again. The parent process will exec() the actual
734 * daemon. We do things this way to ensure that the main PID
735 * of the daemon is the one we initially fork()ed. */
736
737 if ((pam_code = pam_start(name, user, &conv, &handle)) != PAM_SUCCESS) {
738 handle = NULL;
739 goto fail;
740 }
741
742 if (tty)
743 if ((pam_code = pam_set_item(handle, PAM_TTY, tty)) != PAM_SUCCESS)
744 goto fail;
745
746 if ((pam_code = pam_acct_mgmt(handle, PAM_SILENT)) != PAM_SUCCESS)
747 goto fail;
748
749 if ((pam_code = pam_open_session(handle, PAM_SILENT)) != PAM_SUCCESS)
750 goto fail;
751
752 close_session = true;
753
5b6319dc
LP
754 if ((!(e = pam_getenvlist(handle)))) {
755 pam_code = PAM_BUF_ERR;
756 goto fail;
757 }
758
759 /* Block SIGTERM, so that we know that it won't get lost in
760 * the child */
761 if (sigemptyset(&ss) < 0 ||
762 sigaddset(&ss, SIGTERM) < 0 ||
763 sigprocmask(SIG_BLOCK, &ss, &old_ss) < 0)
764 goto fail;
765
766 parent_pid = getpid();
767
768 if ((pam_pid = fork()) < 0)
769 goto fail;
770
771 if (pam_pid == 0) {
772 int sig;
773 int r = EXIT_PAM;
774
775 /* The child's job is to reset the PAM session on
776 * termination */
777
778 /* This string must fit in 10 chars (i.e. the length
5d6b1584
LP
779 * of "/sbin/init"), to look pretty in /bin/ps */
780 rename_process("(sd-pam)");
5b6319dc
LP
781
782 /* Make sure we don't keep open the passed fds in this
783 child. We assume that otherwise only those fds are
784 open here that have been opened by PAM. */
785 close_many(fds, n_fds);
786
940c5210
AK
787 /* Drop privileges - we don't need any to pam_close_session
788 * and this will make PR_SET_PDEATHSIG work in most cases.
789 * If this fails, ignore the error - but expect sd-pam threads
790 * to fail to exit normally */
791 if (setresuid(uid, uid, uid) < 0)
792 log_error("Error: Failed to setresuid() in sd-pam: %s", strerror(-r));
793
794 /* Wait until our parent died. This will only work if
795 * the above setresuid() succeeds, otherwise the kernel
796 * will not allow unprivileged parents kill their privileged
797 * children this way. We rely on the control groups kill logic
5b6319dc
LP
798 * to do the rest for us. */
799 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
800 goto child_finish;
801
802 /* Check if our parent process might already have
803 * died? */
804 if (getppid() == parent_pid) {
3dead8d9
LP
805 for (;;) {
806 if (sigwait(&ss, &sig) < 0) {
807 if (errno == EINTR)
808 continue;
809
810 goto child_finish;
811 }
5b6319dc 812
3dead8d9
LP
813 assert(sig == SIGTERM);
814 break;
815 }
5b6319dc
LP
816 }
817
3dead8d9 818 /* If our parent died we'll end the session */
5b6319dc
LP
819 if (getppid() != parent_pid)
820 if ((pam_code = pam_close_session(handle, PAM_DATA_SILENT)) != PAM_SUCCESS)
821 goto child_finish;
822
823 r = 0;
824
825 child_finish:
826 pam_end(handle, pam_code | PAM_DATA_SILENT);
827 _exit(r);
828 }
829
830 /* If the child was forked off successfully it will do all the
831 * cleanups, so forget about the handle here. */
832 handle = NULL;
833
3b8bddde 834 /* Unblock SIGTERM again in the parent */
5b6319dc
LP
835 if (sigprocmask(SIG_SETMASK, &old_ss, NULL) < 0)
836 goto fail;
837
838 /* We close the log explicitly here, since the PAM modules
839 * might have opened it, but we don't want this fd around. */
840 closelog();
841
aa87e624
LP
842 *pam_env = e;
843 e = NULL;
844
5b6319dc
LP
845 return 0;
846
847fail:
9ba35398
MS
848 if (pam_code != PAM_SUCCESS)
849 err = -EPERM; /* PAM errors do not map to errno */
850 else
851 err = -errno;
852
5b6319dc
LP
853 if (handle) {
854 if (close_session)
855 pam_code = pam_close_session(handle, PAM_DATA_SILENT);
856
857 pam_end(handle, pam_code | PAM_DATA_SILENT);
858 }
859
860 strv_free(e);
861
862 closelog();
863
430c18ed 864 if (pam_pid > 1) {
5b6319dc 865 kill(pam_pid, SIGTERM);
430c18ed
LP
866 kill(pam_pid, SIGCONT);
867 }
5b6319dc 868
9ba35398 869 return err;
5b6319dc
LP
870}
871#endif
872
5d6b1584
LP
873static void rename_process_from_path(const char *path) {
874 char process_name[11];
875 const char *p;
876 size_t l;
877
878 /* This resulting string must fit in 10 chars (i.e. the length
879 * of "/sbin/init") to look pretty in /bin/ps */
880
9eb977db 881 p = path_get_file_name(path);
5d6b1584
LP
882 if (isempty(p)) {
883 rename_process("(...)");
884 return;
885 }
886
887 l = strlen(p);
888 if (l > 8) {
889 /* The end of the process name is usually more
890 * interesting, since the first bit might just be
891 * "systemd-" */
892 p = p + l - 8;
893 l = 8;
894 }
895
896 process_name[0] = '(';
897 memcpy(process_name+1, p, l);
898 process_name[1+l] = ')';
899 process_name[1+l+1] = 0;
900
901 rename_process(process_name);
902}
903
9fb86720 904int exec_spawn(ExecCommand *command,
9e2f7c11 905 char **argv,
81a2b7ce 906 const ExecContext *context,
c2748801 907 int fds[], unsigned n_fds,
1137a57c 908 char **environment,
81a2b7ce
LP
909 bool apply_permissions,
910 bool apply_chroot,
1e3ad081 911 bool apply_tty_stdin,
80876c20 912 bool confirm_spawn,
8e274523 913 CGroupBonding *cgroup_bondings,
ab1f0633 914 CGroupAttribute *cgroup_attributes,
ecedd90f 915 const char *cgroup_suffix,
f2b68789 916 int idle_pipe[2],
81a2b7ce
LP
917 pid_t *ret) {
918
034c6ed7 919 pid_t pid;
8e274523 920 int r;
1a63a750 921 char *line;
4f2d528d 922 int socket_fd;
8c7be95e 923 char **files_env = NULL;
034c6ed7 924
5cb5a6ff
LP
925 assert(command);
926 assert(context);
927 assert(ret);
034c6ed7
LP
928 assert(fds || n_fds <= 0);
929
4f2d528d
LP
930 if (context->std_input == EXEC_INPUT_SOCKET ||
931 context->std_output == EXEC_OUTPUT_SOCKET ||
932 context->std_error == EXEC_OUTPUT_SOCKET) {
933
934 if (n_fds != 1)
935 return -EINVAL;
936
937 socket_fd = fds[0];
938
939 fds = NULL;
940 n_fds = 0;
941 } else
942 socket_fd = -1;
943
8c7be95e
LP
944 if ((r = exec_context_load_environment(context, &files_env)) < 0) {
945 log_error("Failed to load environment files: %s", strerror(-r));
946 return r;
947 }
948
9e2f7c11
LP
949 if (!argv)
950 argv = command->argv;
951
8c7be95e
LP
952 if (!(line = exec_command_line(argv))) {
953 r = -ENOMEM;
954 goto fail_parent;
955 }
1a63a750
LP
956
957 log_debug("About to execute: %s", line);
958 free(line);
acbb0225 959
ab1f0633
LP
960 r = cgroup_bonding_realize_list(cgroup_bondings);
961 if (r < 0)
962 goto fail_parent;
963
964 cgroup_attribute_apply_list(cgroup_attributes, cgroup_bondings);
8e274523 965
8c7be95e
LP
966 if ((pid = fork()) < 0) {
967 r = -errno;
968 goto fail_parent;
969 }
034c6ed7
LP
970
971 if (pid == 0) {
4c2630eb 972 int i, err;
309bff19 973 sigset_t ss;
81a2b7ce
LP
974 const char *username = NULL, *home = NULL;
975 uid_t uid = (uid_t) -1;
976 gid_t gid = (gid_t) -1;
fab56fc5 977 char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
81a2b7ce 978 unsigned n_env = 0;
80876c20 979 int saved_stdout = -1, saved_stdin = -1;
8d53b453 980 bool keep_stdout = false, keep_stdin = false, set_access = false;
309bff19 981
034c6ed7 982 /* child */
5cb5a6ff 983
5d6b1584 984 rename_process_from_path(command->path);
5b6319dc 985
1b91d3e8
LP
986 /* We reset exactly these signals, since they are the
987 * only ones we set to SIG_IGN in the main daemon. All
988 * others we leave untouched because we set them to
989 * SIG_DFL or a valid handler initially, both of which
990 * will be demoted to SIG_DFL. */
991 default_signals(SIGNALS_CRASH_HANDLER,
9a34ec5f 992 SIGNALS_IGNORE, -1);
7b683879 993
353e12c2
LP
994 if (context->ignore_sigpipe)
995 ignore_signals(SIGPIPE, -1);
996
997 assert_se(sigemptyset(&ss) == 0);
998 if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) {
4c2630eb 999 err = -errno;
309bff19 1000 r = EXIT_SIGNAL_MASK;
8c7be95e 1001 goto fail_child;
309bff19
LP
1002 }
1003
f2b68789
LP
1004 if (idle_pipe) {
1005 if (idle_pipe[1] >= 0)
1006 close_nointr_nofail(idle_pipe[1]);
1007 if (idle_pipe[0] >= 0) {
e6a26745 1008 fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
f2b68789
LP
1009 close_nointr_nofail(idle_pipe[0]);
1010 }
1011 }
1012
85d73053
LP
1013 /* Close sockets very early to make sure we don't
1014 * block init reexecution because it cannot bind its
1015 * sockets */
4d8a7798 1016 log_forget_fds();
4c2630eb
MS
1017 err = close_all_fds(socket_fd >= 0 ? &socket_fd : fds,
1018 socket_fd >= 0 ? 1 : n_fds);
1019 if (err < 0) {
fc9b2a84 1020 r = EXIT_FDS;
8c7be95e 1021 goto fail_child;
fc9b2a84
LP
1022 }
1023
74922904 1024 if (!context->same_pgrp)
8d567588 1025 if (setsid() < 0) {
4c2630eb 1026 err = -errno;
8d567588 1027 r = EXIT_SETSID;
8c7be95e 1028 goto fail_child;
8d567588 1029 }
80876c20 1030
c5da34ef
LP
1031 if (context->tcpwrap_name) {
1032 if (socket_fd >= 0)
1033 if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) {
4c2630eb 1034 err = -EACCES;
c5da34ef 1035 r = EXIT_TCPWRAP;
8c7be95e 1036 goto fail_child;
c5da34ef
LP
1037 }
1038
1039 for (i = 0; i < (int) n_fds; i++) {
1040 if (!socket_tcpwrap(fds[i], context->tcpwrap_name)) {
4c2630eb 1041 err = -EACCES;
c5da34ef 1042 r = EXIT_TCPWRAP;
8c7be95e 1043 goto fail_child;
c5da34ef 1044 }
df1f0afe 1045 }
c5da34ef 1046 }
df1f0afe 1047
6ea832a2
LP
1048 exec_context_tty_reset(context);
1049
1e3ad081
LP
1050 /* We skip the confirmation step if we shall not apply the TTY */
1051 if (confirm_spawn &&
1052 (!is_terminal_input(context->std_input) || apply_tty_stdin)) {
80876c20
LP
1053 char response;
1054
1055 /* Set up terminal for the question */
1056 if ((r = setup_confirm_stdio(context,
4c2630eb
MS
1057 &saved_stdin, &saved_stdout))) {
1058 err = -errno;
8c7be95e 1059 goto fail_child;
4c2630eb 1060 }
80876c20
LP
1061
1062 /* Now ask the question. */
9e2f7c11 1063 if (!(line = exec_command_line(argv))) {
4c2630eb 1064 err = -ENOMEM;
80876c20 1065 r = EXIT_MEMORY;
8c7be95e 1066 goto fail_child;
ee2b4894 1067 }
80876c20
LP
1068
1069 r = ask(&response, "yns", "Execute %s? [Yes, No, Skip] ", line);
1070 free(line);
1071
1072 if (r < 0 || response == 'n') {
4c2630eb 1073 err = -ECANCELED;
80876c20 1074 r = EXIT_CONFIRM;
8c7be95e 1075 goto fail_child;
80876c20 1076 } else if (response == 's') {
4c2630eb 1077 err = r = 0;
8c7be95e 1078 goto fail_child;
ee2b4894 1079 }
80876c20
LP
1080
1081 /* Release terminal for the question */
2608882f 1082 if ((r = restore_confirm_stdio(context,
80876c20 1083 &saved_stdin, &saved_stdout,
4c2630eb
MS
1084 &keep_stdin, &keep_stdout))) {
1085 err = -errno;
8c7be95e 1086 goto fail_child;
4c2630eb 1087 }
034c6ed7
LP
1088 }
1089
da726a4d
LP
1090 /* If a socket is connected to STDIN/STDOUT/STDERR, we
1091 * must sure to drop O_NONBLOCK */
1092 if (socket_fd >= 0)
1093 fd_nonblock(socket_fd, false);
1094
4c2630eb
MS
1095 if (!keep_stdin) {
1096 err = setup_input(context, socket_fd, apply_tty_stdin);
1097 if (err < 0) {
80876c20 1098 r = EXIT_STDIN;
8c7be95e 1099 goto fail_child;
80876c20 1100 }
4c2630eb 1101 }
9eba9da4 1102
4c2630eb 1103 if (!keep_stdout) {
9eb977db 1104 err = setup_output(context, socket_fd, path_get_file_name(command->path), apply_tty_stdin);
4c2630eb 1105 if (err < 0) {
80876c20 1106 r = EXIT_STDOUT;
8c7be95e 1107 goto fail_child;
80876c20 1108 }
4c2630eb 1109 }
94f04347 1110
9eb977db 1111 err = setup_error(context, socket_fd, path_get_file_name(command->path), apply_tty_stdin);
4c2630eb 1112 if (err < 0) {
80876c20 1113 r = EXIT_STDERR;
8c7be95e 1114 goto fail_child;
071830ff
LP
1115 }
1116
4c2630eb 1117 if (cgroup_bondings) {
ecedd90f 1118 err = cgroup_bonding_install_list(cgroup_bondings, 0, cgroup_suffix);
4c2630eb 1119 if (err < 0) {
8e274523 1120 r = EXIT_CGROUP;
8c7be95e 1121 goto fail_child;
8e274523 1122 }
4c2630eb 1123 }
8e274523 1124
dd6c17b1 1125 if (context->oom_score_adjust_set) {
fb33a393 1126 char t[16];
034c6ed7 1127
dd6c17b1 1128 snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
fb33a393 1129 char_array_0(t);
034c6ed7 1130
dd6c17b1
LP
1131 if (write_one_line_file("/proc/self/oom_score_adj", t) < 0) {
1132 /* Compatibility with Linux <= 2.6.35 */
1133
1134 int adj;
1135
1136 adj = (context->oom_score_adjust * -OOM_DISABLE) / OOM_SCORE_ADJ_MAX;
1137 adj = CLAMP(adj, OOM_DISABLE, OOM_ADJUST_MAX);
1138
1139 snprintf(t, sizeof(t), "%i", adj);
1140 char_array_0(t);
1141
90a5f6e4
LP
1142 if (write_one_line_file("/proc/self/oom_adj", t) < 0
1143 && errno != EACCES) {
4c2630eb 1144 err = -errno;
dd6c17b1 1145 r = EXIT_OOM_ADJUST;
8c7be95e 1146 goto fail_child;
dd6c17b1 1147 }
fb33a393 1148 }
034c6ed7
LP
1149 }
1150
fb33a393
LP
1151 if (context->nice_set)
1152 if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
4c2630eb 1153 err = -errno;
fb33a393 1154 r = EXIT_NICE;
8c7be95e 1155 goto fail_child;
fb33a393
LP
1156 }
1157
94f04347
LP
1158 if (context->cpu_sched_set) {
1159 struct sched_param param;
1160
1161 zero(param);
1162 param.sched_priority = context->cpu_sched_priority;
1163
38b48754
LP
1164 if (sched_setscheduler(0, context->cpu_sched_policy |
1165 (context->cpu_sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0), &param) < 0) {
4c2630eb 1166 err = -errno;
94f04347 1167 r = EXIT_SETSCHEDULER;
8c7be95e 1168 goto fail_child;
94f04347
LP
1169 }
1170 }
1171
82c121a4
LP
1172 if (context->cpuset)
1173 if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
4c2630eb 1174 err = -errno;
94f04347 1175 r = EXIT_CPUAFFINITY;
8c7be95e 1176 goto fail_child;
94f04347
LP
1177 }
1178
9eba9da4
LP
1179 if (context->ioprio_set)
1180 if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
4c2630eb 1181 err = -errno;
9eba9da4 1182 r = EXIT_IOPRIO;
8c7be95e 1183 goto fail_child;
9eba9da4
LP
1184 }
1185
03fae018
LP
1186 if (context->timer_slack_nsec_set)
1187 if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
4c2630eb 1188 err = -errno;
94f04347 1189 r = EXIT_TIMERSLACK;
8c7be95e 1190 goto fail_child;
94f04347
LP
1191 }
1192
169c1bda 1193 if (context->utmp_id)
0ad26e09 1194 utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path);
169c1bda 1195
81a2b7ce
LP
1196 if (context->user) {
1197 username = context->user;
4c2630eb
MS
1198 err = get_user_creds(&username, &uid, &gid, &home);
1199 if (err < 0) {
81a2b7ce 1200 r = EXIT_USER;
8c7be95e 1201 goto fail_child;
81a2b7ce 1202 }
d8b4e2e9 1203
4c2630eb
MS
1204 if (is_terminal_input(context->std_input)) {
1205 err = chown_terminal(STDIN_FILENO, uid);
1206 if (err < 0) {
d8b4e2e9 1207 r = EXIT_STDIN;
8c7be95e 1208 goto fail_child;
d8b4e2e9 1209 }
4c2630eb 1210 }
64747e2d 1211
4c2630eb
MS
1212 if (cgroup_bondings && context->control_group_modify) {
1213 err = cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid);
1214 if (err >= 0)
891703e1 1215 err = cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid, context->control_group_persistent);
4c2630eb 1216 if (err < 0) {
64747e2d
LP
1217 r = EXIT_CGROUP;
1218 goto fail_child;
1219 }
8d53b453
LP
1220
1221 set_access = true;
1222 }
1223 }
1224
891703e1
KS
1225 if (cgroup_bondings && !set_access && context->control_group_persistent >= 0) {
1226 err = cgroup_bonding_set_task_access_list(cgroup_bondings, (mode_t) -1, (uid_t) -1, (uid_t) -1, context->control_group_persistent);
8d53b453
LP
1227 if (err < 0) {
1228 r = EXIT_CGROUP;
1229 goto fail_child;
4c2630eb 1230 }
81a2b7ce
LP
1231 }
1232
4c2630eb
MS
1233 if (apply_permissions) {
1234 err = enforce_groups(context, username, gid);
1235 if (err < 0) {
3b8bddde
LP
1236 r = EXIT_GROUP;
1237 goto fail_child;
1238 }
4c2630eb 1239 }
3b8bddde
LP
1240
1241 umask(context->umask);
1242
5b6319dc
LP
1243#ifdef HAVE_PAM
1244 if (context->pam_name && username) {
940c5210 1245 err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
4c2630eb 1246 if (err < 0) {
5b6319dc 1247 r = EXIT_PAM;
8c7be95e 1248 goto fail_child;
5b6319dc
LP
1249 }
1250 }
1251#endif
ff01d048
LP
1252 if (context->private_network) {
1253 if (unshare(CLONE_NEWNET) < 0) {
4c2630eb 1254 err = -errno;
ff01d048
LP
1255 r = EXIT_NETWORK;
1256 goto fail_child;
1257 }
1258
1259 loopback_setup();
1260 }
5b6319dc 1261
04aa0cb9
LP
1262 if (strv_length(context->read_write_dirs) > 0 ||
1263 strv_length(context->read_only_dirs) > 0 ||
1264 strv_length(context->inaccessible_dirs) > 0 ||
1265 context->mount_flags != MS_SHARED ||
4c2630eb
MS
1266 context->private_tmp) {
1267 err = setup_namespace(context->read_write_dirs,
1268 context->read_only_dirs,
1269 context->inaccessible_dirs,
1270 context->private_tmp,
1271 context->mount_flags);
1272 if (err < 0) {
1273 r = EXIT_NAMESPACE;
8c7be95e 1274 goto fail_child;
4c2630eb
MS
1275 }
1276 }
04aa0cb9 1277
81a2b7ce
LP
1278 if (apply_chroot) {
1279 if (context->root_directory)
1280 if (chroot(context->root_directory) < 0) {
4c2630eb 1281 err = -errno;
81a2b7ce 1282 r = EXIT_CHROOT;
8c7be95e 1283 goto fail_child;
81a2b7ce
LP
1284 }
1285
1286 if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
4c2630eb 1287 err = -errno;
81a2b7ce 1288 r = EXIT_CHDIR;
8c7be95e 1289 goto fail_child;
81a2b7ce
LP
1290 }
1291 } else {
1292
1293 char *d;
1294
1295 if (asprintf(&d, "%s/%s",
1296 context->root_directory ? context->root_directory : "",
1297 context->working_directory ? context->working_directory : "") < 0) {
4c2630eb 1298 err = -ENOMEM;
81a2b7ce 1299 r = EXIT_MEMORY;
8c7be95e 1300 goto fail_child;
81a2b7ce
LP
1301 }
1302
1303 if (chdir(d) < 0) {
4c2630eb 1304 err = -errno;
81a2b7ce
LP
1305 free(d);
1306 r = EXIT_CHDIR;
8c7be95e 1307 goto fail_child;
81a2b7ce
LP
1308 }
1309
1310 free(d);
1311 }
1312
fc9b2a84
LP
1313 /* We repeat the fd closing here, to make sure that
1314 * nothing is leaked from the PAM modules */
4c2630eb
MS
1315 err = close_all_fds(fds, n_fds);
1316 if (err >= 0)
1317 err = shift_fds(fds, n_fds);
1318 if (err >= 0)
1319 err = flags_fds(fds, n_fds, context->non_blocking);
1320 if (err < 0) {
034c6ed7 1321 r = EXIT_FDS;
8c7be95e 1322 goto fail_child;
034c6ed7
LP
1323 }
1324
81a2b7ce 1325 if (apply_permissions) {
034c6ed7 1326
81a2b7ce
LP
1327 for (i = 0; i < RLIMIT_NLIMITS; i++) {
1328 if (!context->rlimit[i])
1329 continue;
1330
68faf98c 1331 if (setrlimit_closest(i, context->rlimit[i]) < 0) {
4c2630eb 1332 err = -errno;
81a2b7ce 1333 r = EXIT_LIMITS;
8c7be95e 1334 goto fail_child;
81a2b7ce 1335 }
034c6ed7 1336 }
034c6ed7 1337
4c2630eb 1338 if (context->capability_bounding_set_drop) {
ec8927ca 1339 err = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
4c2630eb 1340 if (err < 0) {
73090dc8
LP
1341 r = EXIT_CAPABILITIES;
1342 goto fail_child;
1343 }
4c2630eb 1344 }
260abb78 1345
4c2630eb
MS
1346 if (context->user) {
1347 err = enforce_user(context, uid);
1348 if (err < 0) {
81a2b7ce 1349 r = EXIT_USER;
8c7be95e 1350 goto fail_child;
81a2b7ce 1351 }
4c2630eb 1352 }
81a2b7ce 1353
35b8ca3a 1354 /* PR_GET_SECUREBITS is not privileged, while
693ced48
LP
1355 * PR_SET_SECUREBITS is. So to suppress
1356 * potential EPERMs we'll try not to call
1357 * PR_SET_SECUREBITS unless necessary. */
1358 if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
1359 if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
4c2630eb 1360 err = -errno;
693ced48 1361 r = EXIT_SECUREBITS;
8c7be95e 1362 goto fail_child;
693ced48 1363 }
81a2b7ce
LP
1364
1365 if (context->capabilities)
1366 if (cap_set_proc(context->capabilities) < 0) {
4c2630eb 1367 err = -errno;
81a2b7ce 1368 r = EXIT_CAPABILITIES;
8c7be95e 1369 goto fail_child;
81a2b7ce 1370 }
94f04347
LP
1371 }
1372
e3aa71c3 1373 if (!(our_env = new0(char*, 7))) {
4c2630eb 1374 err = -ENOMEM;
81a2b7ce 1375 r = EXIT_MEMORY;
8c7be95e 1376 goto fail_child;
81a2b7ce 1377 }
034c6ed7 1378
81a2b7ce 1379 if (n_fds > 0)
bb00e604 1380 if (asprintf(our_env + n_env++, "LISTEN_PID=%lu", (unsigned long) getpid()) < 0 ||
81a2b7ce 1381 asprintf(our_env + n_env++, "LISTEN_FDS=%u", n_fds) < 0) {
4c2630eb 1382 err = -ENOMEM;
81a2b7ce 1383 r = EXIT_MEMORY;
8c7be95e 1384 goto fail_child;
81a2b7ce 1385 }
034c6ed7 1386
81a2b7ce
LP
1387 if (home)
1388 if (asprintf(our_env + n_env++, "HOME=%s", home) < 0) {
4c2630eb 1389 err = -ENOMEM;
81a2b7ce 1390 r = EXIT_MEMORY;
8c7be95e 1391 goto fail_child;
81a2b7ce 1392 }
034c6ed7 1393
81a2b7ce
LP
1394 if (username)
1395 if (asprintf(our_env + n_env++, "LOGNAME=%s", username) < 0 ||
1396 asprintf(our_env + n_env++, "USER=%s", username) < 0) {
4c2630eb 1397 err = -ENOMEM;
81a2b7ce 1398 r = EXIT_MEMORY;
8c7be95e 1399 goto fail_child;
81a2b7ce 1400 }
034c6ed7 1401
e3aa71c3
LP
1402 if (is_terminal_input(context->std_input) ||
1403 context->std_output == EXEC_OUTPUT_TTY ||
1404 context->std_error == EXEC_OUTPUT_TTY)
1405 if (!(our_env[n_env++] = strdup(default_term_for_tty(tty_path(context))))) {
4c2630eb 1406 err = -ENOMEM;
e3aa71c3 1407 r = EXIT_MEMORY;
8c7be95e 1408 goto fail_child;
e3aa71c3
LP
1409 }
1410
1411 assert(n_env <= 7);
4e85aff4 1412
5b6319dc 1413 if (!(final_env = strv_env_merge(
8c7be95e 1414 5,
5b6319dc
LP
1415 environment,
1416 our_env,
1417 context->environment,
8c7be95e 1418 files_env,
5b6319dc
LP
1419 pam_env,
1420 NULL))) {
4c2630eb 1421 err = -ENOMEM;
81a2b7ce 1422 r = EXIT_MEMORY;
8c7be95e 1423 goto fail_child;
81a2b7ce 1424 }
034c6ed7 1425
fab56fc5 1426 if (!(final_argv = replace_env_argv(argv, final_env))) {
4c2630eb 1427 err = -ENOMEM;
fab56fc5 1428 r = EXIT_MEMORY;
8c7be95e 1429 goto fail_child;
fab56fc5
LP
1430 }
1431
a6ff950e
LP
1432 final_env = strv_env_clean(final_env);
1433
fab56fc5 1434 execve(command->path, final_argv, final_env);
4c2630eb 1435 err = -errno;
034c6ed7
LP
1436 r = EXIT_EXEC;
1437
8c7be95e 1438 fail_child:
4c2630eb
MS
1439 if (r != 0) {
1440 log_open();
1441 log_warning("Failed at step %s spawning %s: %s",
1442 exit_status_to_string(r, EXIT_STATUS_SYSTEMD),
1443 command->path, strerror(-err));
1444 }
1445
81a2b7ce
LP
1446 strv_free(our_env);
1447 strv_free(final_env);
5b6319dc 1448 strv_free(pam_env);
8c7be95e 1449 strv_free(files_env);
fab56fc5 1450 strv_free(final_argv);
81a2b7ce 1451
80876c20
LP
1452 if (saved_stdin >= 0)
1453 close_nointr_nofail(saved_stdin);
1454
1455 if (saved_stdout >= 0)
1456 close_nointr_nofail(saved_stdout);
1457
034c6ed7
LP
1458 _exit(r);
1459 }
1460
8c7be95e
LP
1461 strv_free(files_env);
1462
80876c20
LP
1463 /* We add the new process to the cgroup both in the child (so
1464 * that we can be sure that no user code is ever executed
1465 * outside of the cgroup) and in the parent (so that we can be
1466 * sure that when we kill the cgroup the process will be
1467 * killed too). */
1468 if (cgroup_bondings)
ecedd90f 1469 cgroup_bonding_install_list(cgroup_bondings, pid, cgroup_suffix);
2da3263a 1470
bb00e604 1471 log_debug("Forked %s as %lu", command->path, (unsigned long) pid);
2da3263a 1472
b58b4116 1473 exec_status_start(&command->exec_status, pid);
9fb86720 1474
034c6ed7 1475 *ret = pid;
5cb5a6ff 1476 return 0;
8c7be95e
LP
1477
1478fail_parent:
1479 strv_free(files_env);
1480
1481 return r;
5cb5a6ff
LP
1482}
1483
034c6ed7
LP
1484void exec_context_init(ExecContext *c) {
1485 assert(c);
1486
4c12626c 1487 c->umask = 0022;
9eba9da4 1488 c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
94f04347 1489 c->cpu_sched_policy = SCHED_OTHER;
071830ff 1490 c->syslog_priority = LOG_DAEMON|LOG_INFO;
74922904 1491 c->syslog_level_prefix = true;
15ae422b 1492 c->mount_flags = MS_SHARED;
2e22afe9 1493 c->kill_signal = SIGTERM;
ba035df2 1494 c->send_sigkill = true;
891703e1 1495 c->control_group_persistent = -1;
353e12c2 1496 c->ignore_sigpipe = true;
034c6ed7
LP
1497}
1498
1499void exec_context_done(ExecContext *c) {
5cb5a6ff
LP
1500 unsigned l;
1501
1502 assert(c);
1503
1504 strv_free(c->environment);
034c6ed7 1505 c->environment = NULL;
5cb5a6ff 1506
8c7be95e
LP
1507 strv_free(c->environment_files);
1508 c->environment_files = NULL;
1509
034c6ed7 1510 for (l = 0; l < ELEMENTSOF(c->rlimit); l++) {
5cb5a6ff 1511 free(c->rlimit[l]);
034c6ed7
LP
1512 c->rlimit[l] = NULL;
1513 }
1514
9eba9da4
LP
1515 free(c->working_directory);
1516 c->working_directory = NULL;
1517 free(c->root_directory);
1518 c->root_directory = NULL;
5cb5a6ff 1519
80876c20
LP
1520 free(c->tty_path);
1521 c->tty_path = NULL;
1522
df1f0afe
LP
1523 free(c->tcpwrap_name);
1524 c->tcpwrap_name = NULL;
1525
071830ff
LP
1526 free(c->syslog_identifier);
1527 c->syslog_identifier = NULL;
1528
5cb5a6ff 1529 free(c->user);
034c6ed7
LP
1530 c->user = NULL;
1531
5cb5a6ff 1532 free(c->group);
034c6ed7
LP
1533 c->group = NULL;
1534
1535 strv_free(c->supplementary_groups);
1536 c->supplementary_groups = NULL;
94f04347 1537
5b6319dc
LP
1538 free(c->pam_name);
1539 c->pam_name = NULL;
1540
94f04347
LP
1541 if (c->capabilities) {
1542 cap_free(c->capabilities);
1543 c->capabilities = NULL;
1544 }
15ae422b
LP
1545
1546 strv_free(c->read_only_dirs);
1547 c->read_only_dirs = NULL;
1548
1549 strv_free(c->read_write_dirs);
1550 c->read_write_dirs = NULL;
1551
1552 strv_free(c->inaccessible_dirs);
1553 c->inaccessible_dirs = NULL;
82c121a4
LP
1554
1555 if (c->cpuset)
1556 CPU_FREE(c->cpuset);
86a3475b
LP
1557
1558 free(c->utmp_id);
1559 c->utmp_id = NULL;
5cb5a6ff
LP
1560}
1561
43d0fcbd
LP
1562void exec_command_done(ExecCommand *c) {
1563 assert(c);
1564
1565 free(c->path);
1566 c->path = NULL;
1567
1568 strv_free(c->argv);
1569 c->argv = NULL;
1570}
1571
1572void exec_command_done_array(ExecCommand *c, unsigned n) {
1573 unsigned i;
1574
1575 for (i = 0; i < n; i++)
1576 exec_command_done(c+i);
1577}
1578
5cb5a6ff
LP
1579void exec_command_free_list(ExecCommand *c) {
1580 ExecCommand *i;
1581
1582 while ((i = c)) {
034c6ed7 1583 LIST_REMOVE(ExecCommand, command, c, i);
43d0fcbd 1584 exec_command_done(i);
5cb5a6ff
LP
1585 free(i);
1586 }
1587}
1588
034c6ed7
LP
1589void exec_command_free_array(ExecCommand **c, unsigned n) {
1590 unsigned i;
1591
1592 for (i = 0; i < n; i++) {
1593 exec_command_free_list(c[i]);
1594 c[i] = NULL;
1595 }
1596}
1597
8c7be95e
LP
1598int exec_context_load_environment(const ExecContext *c, char ***l) {
1599 char **i, **r = NULL;
1600
1601 assert(c);
1602 assert(l);
1603
1604 STRV_FOREACH(i, c->environment_files) {
1605 char *fn;
1606 int k;
1607 bool ignore = false;
1608 char **p;
1609
1610 fn = *i;
1611
1612 if (fn[0] == '-') {
1613 ignore = true;
1614 fn ++;
1615 }
1616
1617 if (!path_is_absolute(fn)) {
1618
1619 if (ignore)
1620 continue;
1621
1622 strv_free(r);
1623 return -EINVAL;
1624 }
1625
1626 if ((k = load_env_file(fn, &p)) < 0) {
1627
1628 if (ignore)
1629 continue;
1630
1631 strv_free(r);
1632 return k;
1633 }
1634
1635 if (r == NULL)
1636 r = p;
1637 else {
1638 char **m;
1639
1640 m = strv_env_merge(2, r, p);
1641 strv_free(r);
1642 strv_free(p);
1643
1644 if (!m)
1645 return -ENOMEM;
1646
1647 r = m;
1648 }
1649 }
1650
1651 *l = r;
1652
1653 return 0;
1654}
1655
15ae422b
LP
1656static void strv_fprintf(FILE *f, char **l) {
1657 char **g;
1658
1659 assert(f);
1660
1661 STRV_FOREACH(g, l)
1662 fprintf(f, " %s", *g);
1663}
1664
5cb5a6ff 1665void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
94f04347
LP
1666 char ** e;
1667 unsigned i;
9eba9da4 1668
5cb5a6ff
LP
1669 assert(c);
1670 assert(f);
1671
1672 if (!prefix)
1673 prefix = "";
1674
1675 fprintf(f,
94f04347
LP
1676 "%sUMask: %04o\n"
1677 "%sWorkingDirectory: %s\n"
451a074f 1678 "%sRootDirectory: %s\n"
15ae422b 1679 "%sNonBlocking: %s\n"
64747e2d 1680 "%sPrivateTmp: %s\n"
ff01d048 1681 "%sControlGroupModify: %s\n"
891703e1 1682 "%sControlGroupPersistent: %s\n"
ff01d048 1683 "%sPrivateNetwork: %s\n",
5cb5a6ff 1684 prefix, c->umask,
9eba9da4 1685 prefix, c->working_directory ? c->working_directory : "/",
451a074f 1686 prefix, c->root_directory ? c->root_directory : "/",
15ae422b 1687 prefix, yes_no(c->non_blocking),
64747e2d 1688 prefix, yes_no(c->private_tmp),
ff01d048 1689 prefix, yes_no(c->control_group_modify),
891703e1 1690 prefix, yes_no(c->control_group_persistent),
ff01d048 1691 prefix, yes_no(c->private_network));
fb33a393 1692
8c7be95e
LP
1693 STRV_FOREACH(e, c->environment)
1694 fprintf(f, "%sEnvironment: %s\n", prefix, *e);
1695
1696 STRV_FOREACH(e, c->environment_files)
1697 fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
94f04347 1698
df1f0afe
LP
1699 if (c->tcpwrap_name)
1700 fprintf(f,
1701 "%sTCPWrapName: %s\n",
1702 prefix, c->tcpwrap_name);
1703
fb33a393
LP
1704 if (c->nice_set)
1705 fprintf(f,
1706 "%sNice: %i\n",
1707 prefix, c->nice);
1708
dd6c17b1 1709 if (c->oom_score_adjust_set)
fb33a393 1710 fprintf(f,
dd6c17b1
LP
1711 "%sOOMScoreAdjust: %i\n",
1712 prefix, c->oom_score_adjust);
9eba9da4 1713
94f04347
LP
1714 for (i = 0; i < RLIM_NLIMITS; i++)
1715 if (c->rlimit[i])
ea430986 1716 fprintf(f, "%s%s: %llu\n", prefix, rlimit_to_string(i), (unsigned long long) c->rlimit[i]->rlim_max);
94f04347 1717
9eba9da4
LP
1718 if (c->ioprio_set)
1719 fprintf(f,
1720 "%sIOSchedulingClass: %s\n"
1721 "%sIOPriority: %i\n",
94f04347 1722 prefix, ioprio_class_to_string(IOPRIO_PRIO_CLASS(c->ioprio)),
9eba9da4 1723 prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
94f04347
LP
1724
1725 if (c->cpu_sched_set)
1726 fprintf(f,
1727 "%sCPUSchedulingPolicy: %s\n"
38b48754
LP
1728 "%sCPUSchedulingPriority: %i\n"
1729 "%sCPUSchedulingResetOnFork: %s\n",
94f04347 1730 prefix, sched_policy_to_string(c->cpu_sched_policy),
38b48754
LP
1731 prefix, c->cpu_sched_priority,
1732 prefix, yes_no(c->cpu_sched_reset_on_fork));
94f04347 1733
82c121a4 1734 if (c->cpuset) {
94f04347 1735 fprintf(f, "%sCPUAffinity:", prefix);
82c121a4
LP
1736 for (i = 0; i < c->cpuset_ncpus; i++)
1737 if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
94f04347
LP
1738 fprintf(f, " %i", i);
1739 fputs("\n", f);
1740 }
1741
03fae018
LP
1742 if (c->timer_slack_nsec_set)
1743 fprintf(f, "%sTimerSlackNSec: %lu\n", prefix, c->timer_slack_nsec);
94f04347
LP
1744
1745 fprintf(f,
80876c20
LP
1746 "%sStandardInput: %s\n"
1747 "%sStandardOutput: %s\n"
1748 "%sStandardError: %s\n",
1749 prefix, exec_input_to_string(c->std_input),
1750 prefix, exec_output_to_string(c->std_output),
1751 prefix, exec_output_to_string(c->std_error));
1752
1753 if (c->tty_path)
1754 fprintf(f,
6ea832a2
LP
1755 "%sTTYPath: %s\n"
1756 "%sTTYReset: %s\n"
1757 "%sTTYVHangup: %s\n"
1758 "%sTTYVTDisallocate: %s\n",
1759 prefix, c->tty_path,
1760 prefix, yes_no(c->tty_reset),
1761 prefix, yes_no(c->tty_vhangup),
1762 prefix, yes_no(c->tty_vt_disallocate));
94f04347 1763
706343f4
LP
1764 if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG || c->std_output == EXEC_OUTPUT_JOURNAL ||
1765 c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE ||
1766 c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG || c->std_error == EXEC_OUTPUT_JOURNAL ||
1767 c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE)
94f04347
LP
1768 fprintf(f,
1769 "%sSyslogFacility: %s\n"
1770 "%sSyslogLevel: %s\n",
7d76f312 1771 prefix, log_facility_unshifted_to_string(c->syslog_priority >> 3),
94f04347
LP
1772 prefix, log_level_to_string(LOG_PRI(c->syslog_priority)));
1773
1774 if (c->capabilities) {
1775 char *t;
1776 if ((t = cap_to_text(c->capabilities, NULL))) {
1777 fprintf(f, "%sCapabilities: %s\n",
1778 prefix, t);
1779 cap_free(t);
1780 }
1781 }
1782
1783 if (c->secure_bits)
1784 fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
1785 prefix,
1786 (c->secure_bits & SECURE_KEEP_CAPS) ? " keep-caps" : "",
1787 (c->secure_bits & SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
1788 (c->secure_bits & SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
1789 (c->secure_bits & SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
1790 (c->secure_bits & SECURE_NOROOT) ? " noroot" : "",
1791 (c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
1792
1793 if (c->capability_bounding_set_drop) {
ae556c21 1794 unsigned long l;
260abb78 1795 fprintf(f, "%sCapabilityBoundingSet:", prefix);
94f04347 1796
64685e0c 1797 for (l = 0; l <= cap_last_cap(); l++)
ae556c21 1798 if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l))) {
94f04347
LP
1799 char *t;
1800
ae556c21 1801 if ((t = cap_to_name(l))) {
94f04347 1802 fprintf(f, " %s", t);
260abb78 1803 cap_free(t);
94f04347
LP
1804 }
1805 }
1806
1807 fputs("\n", f);
1808 }
1809
1810 if (c->user)
f2d3769a 1811 fprintf(f, "%sUser: %s\n", prefix, c->user);
94f04347 1812 if (c->group)
f2d3769a 1813 fprintf(f, "%sGroup: %s\n", prefix, c->group);
94f04347 1814
15ae422b 1815 if (strv_length(c->supplementary_groups) > 0) {
94f04347 1816 fprintf(f, "%sSupplementaryGroups:", prefix);
15ae422b
LP
1817 strv_fprintf(f, c->supplementary_groups);
1818 fputs("\n", f);
1819 }
94f04347 1820
5b6319dc 1821 if (c->pam_name)
f2d3769a 1822 fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
5b6319dc 1823
15ae422b
LP
1824 if (strv_length(c->read_write_dirs) > 0) {
1825 fprintf(f, "%sReadWriteDirs:", prefix);
1826 strv_fprintf(f, c->read_write_dirs);
1827 fputs("\n", f);
1828 }
1829
1830 if (strv_length(c->read_only_dirs) > 0) {
1831 fprintf(f, "%sReadOnlyDirs:", prefix);
1832 strv_fprintf(f, c->read_only_dirs);
1833 fputs("\n", f);
1834 }
94f04347 1835
15ae422b
LP
1836 if (strv_length(c->inaccessible_dirs) > 0) {
1837 fprintf(f, "%sInaccessibleDirs:", prefix);
1838 strv_fprintf(f, c->inaccessible_dirs);
94f04347
LP
1839 fputs("\n", f);
1840 }
2e22afe9
LP
1841
1842 fprintf(f,
1843 "%sKillMode: %s\n"
ba035df2 1844 "%sKillSignal: SIG%s\n"
353e12c2
LP
1845 "%sSendSIGKILL: %s\n"
1846 "%sIgnoreSIGPIPE: %s\n",
2e22afe9 1847 prefix, kill_mode_to_string(c->kill_mode),
ba035df2 1848 prefix, signal_to_string(c->kill_signal),
353e12c2
LP
1849 prefix, yes_no(c->send_sigkill),
1850 prefix, yes_no(c->ignore_sigpipe));
169c1bda
LP
1851
1852 if (c->utmp_id)
1853 fprintf(f,
1854 "%sUtmpIdentifier: %s\n",
1855 prefix, c->utmp_id);
5cb5a6ff
LP
1856}
1857
b58b4116 1858void exec_status_start(ExecStatus *s, pid_t pid) {
034c6ed7 1859 assert(s);
5cb5a6ff 1860
b58b4116
LP
1861 zero(*s);
1862 s->pid = pid;
1863 dual_timestamp_get(&s->start_timestamp);
1864}
1865
6ea832a2 1866void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status) {
b58b4116
LP
1867 assert(s);
1868
0b1f4ae6 1869 if (s->pid && s->pid != pid)
b58b4116
LP
1870 zero(*s);
1871
034c6ed7 1872 s->pid = pid;
63983207 1873 dual_timestamp_get(&s->exit_timestamp);
9fb86720 1874
034c6ed7
LP
1875 s->code = code;
1876 s->status = status;
169c1bda 1877
6ea832a2
LP
1878 if (context) {
1879 if (context->utmp_id)
1880 utmp_put_dead_process(context->utmp_id, pid, code, status);
1881
1882 exec_context_tty_reset(context);
1883 }
9fb86720
LP
1884}
1885
1886void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
1887 char buf[FORMAT_TIMESTAMP_MAX];
1888
1889 assert(s);
1890 assert(f);
1891
1892 if (!prefix)
1893 prefix = "";
1894
1895 if (s->pid <= 0)
1896 return;
1897
1898 fprintf(f,
bb00e604
LP
1899 "%sPID: %lu\n",
1900 prefix, (unsigned long) s->pid);
9fb86720 1901
63983207 1902 if (s->start_timestamp.realtime > 0)
9fb86720
LP
1903 fprintf(f,
1904 "%sStart Timestamp: %s\n",
63983207 1905 prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
9fb86720 1906
63983207 1907 if (s->exit_timestamp.realtime > 0)
9fb86720
LP
1908 fprintf(f,
1909 "%sExit Timestamp: %s\n"
1910 "%sExit Code: %s\n"
1911 "%sExit Status: %i\n",
63983207 1912 prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
9fb86720
LP
1913 prefix, sigchld_code_to_string(s->code),
1914 prefix, s->status);
5cb5a6ff 1915}
44d8db9e 1916
9e2f7c11 1917char *exec_command_line(char **argv) {
44d8db9e
LP
1918 size_t k;
1919 char *n, *p, **a;
1920 bool first = true;
1921
9e2f7c11 1922 assert(argv);
44d8db9e 1923
9164977d 1924 k = 1;
9e2f7c11 1925 STRV_FOREACH(a, argv)
44d8db9e
LP
1926 k += strlen(*a)+3;
1927
1928 if (!(n = new(char, k)))
1929 return NULL;
1930
1931 p = n;
9e2f7c11 1932 STRV_FOREACH(a, argv) {
44d8db9e
LP
1933
1934 if (!first)
1935 *(p++) = ' ';
1936 else
1937 first = false;
1938
1939 if (strpbrk(*a, WHITESPACE)) {
1940 *(p++) = '\'';
1941 p = stpcpy(p, *a);
1942 *(p++) = '\'';
1943 } else
1944 p = stpcpy(p, *a);
1945
1946 }
1947
9164977d
LP
1948 *p = 0;
1949
44d8db9e
LP
1950 /* FIXME: this doesn't really handle arguments that have
1951 * spaces and ticks in them */
1952
1953 return n;
1954}
1955
1956void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
9fb86720
LP
1957 char *p2;
1958 const char *prefix2;
1959
44d8db9e
LP
1960 char *cmd;
1961
1962 assert(c);
1963 assert(f);
1964
1965 if (!prefix)
1966 prefix = "";
9fb86720
LP
1967 p2 = strappend(prefix, "\t");
1968 prefix2 = p2 ? p2 : prefix;
44d8db9e 1969
9e2f7c11 1970 cmd = exec_command_line(c->argv);
44d8db9e
LP
1971
1972 fprintf(f,
1973 "%sCommand Line: %s\n",
1974 prefix, cmd ? cmd : strerror(ENOMEM));
1975
1976 free(cmd);
9fb86720
LP
1977
1978 exec_status_dump(&c->exec_status, f, prefix2);
1979
1980 free(p2);
44d8db9e
LP
1981}
1982
1983void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
1984 assert(f);
1985
1986 if (!prefix)
1987 prefix = "";
1988
1989 LIST_FOREACH(command, c, c)
1990 exec_command_dump(c, f, prefix);
1991}
94f04347 1992
a6a80b4f
LP
1993void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
1994 ExecCommand *end;
1995
1996 assert(l);
1997 assert(e);
1998
1999 if (*l) {
35b8ca3a 2000 /* It's kind of important, that we keep the order here */
a6a80b4f
LP
2001 LIST_FIND_TAIL(ExecCommand, command, *l, end);
2002 LIST_INSERT_AFTER(ExecCommand, command, *l, end, e);
2003 } else
2004 *l = e;
2005}
2006
26fd040d
LP
2007int exec_command_set(ExecCommand *c, const char *path, ...) {
2008 va_list ap;
2009 char **l, *p;
2010
2011 assert(c);
2012 assert(path);
2013
2014 va_start(ap, path);
2015 l = strv_new_ap(path, ap);
2016 va_end(ap);
2017
2018 if (!l)
2019 return -ENOMEM;
2020
2021 if (!(p = strdup(path))) {
2022 strv_free(l);
2023 return -ENOMEM;
2024 }
2025
2026 free(c->path);
2027 c->path = p;
2028
2029 strv_free(c->argv);
2030 c->argv = l;
2031
2032 return 0;
2033}
2034
80876c20
LP
2035static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
2036 [EXEC_INPUT_NULL] = "null",
2037 [EXEC_INPUT_TTY] = "tty",
2038 [EXEC_INPUT_TTY_FORCE] = "tty-force",
4f2d528d
LP
2039 [EXEC_INPUT_TTY_FAIL] = "tty-fail",
2040 [EXEC_INPUT_SOCKET] = "socket"
80876c20
LP
2041};
2042
8a0867d6
LP
2043DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
2044
94f04347 2045static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
80876c20 2046 [EXEC_OUTPUT_INHERIT] = "inherit",
94f04347 2047 [EXEC_OUTPUT_NULL] = "null",
80876c20 2048 [EXEC_OUTPUT_TTY] = "tty",
94f04347 2049 [EXEC_OUTPUT_SYSLOG] = "syslog",
28dbc1e8 2050 [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
9a6bca7a 2051 [EXEC_OUTPUT_KMSG] = "kmsg",
28dbc1e8 2052 [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
706343f4
LP
2053 [EXEC_OUTPUT_JOURNAL] = "journal",
2054 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
4f2d528d 2055 [EXEC_OUTPUT_SOCKET] = "socket"
94f04347
LP
2056};
2057
2058DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
2059
8a0867d6
LP
2060static const char* const kill_mode_table[_KILL_MODE_MAX] = {
2061 [KILL_CONTROL_GROUP] = "control-group",
8a0867d6
LP
2062 [KILL_PROCESS] = "process",
2063 [KILL_NONE] = "none"
2064};
2065
2066DEFINE_STRING_TABLE_LOOKUP(kill_mode, KillMode);
2067
2068static const char* const kill_who_table[_KILL_WHO_MAX] = {
2069 [KILL_MAIN] = "main",
2070 [KILL_CONTROL] = "control",
2071 [KILL_ALL] = "all"
2072};
2073
2074DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);