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