]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/execute.c
9b953f980fd08387d22623d2ed59195c81d93e5d
[thirdparty/systemd.git] / src / core / execute.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <poll.h>
6 #include <sys/file.h>
7 #include <sys/mman.h>
8 #include <sys/personality.h>
9 #include <sys/prctl.h>
10 #include <sys/shm.h>
11 #include <sys/types.h>
12 #include <sys/un.h>
13 #include <unistd.h>
14 #include <utmpx.h>
15
16 #include <linux/fs.h> /* Must be included after <sys/mount.h> */
17
18 #include "sd-messages.h"
19
20 #include "af-list.h"
21 #include "alloc-util.h"
22 #include "async.h"
23 #include "cap-list.h"
24 #include "capability-util.h"
25 #include "cgroup-setup.h"
26 #include "constants.h"
27 #include "cpu-set-util.h"
28 #include "dev-setup.h"
29 #include "env-file.h"
30 #include "env-util.h"
31 #include "errno-list.h"
32 #include "escape.h"
33 #include "exec-credential.h"
34 #include "execute.h"
35 #include "execute-serialize.h"
36 #include "exit-status.h"
37 #include "fd-util.h"
38 #include "fileio.h"
39 #include "format-util.h"
40 #include "glob-util.h"
41 #include "hexdecoct.h"
42 #include "ioprio-util.h"
43 #include "lock-util.h"
44 #include "log.h"
45 #include "macro.h"
46 #include "manager.h"
47 #include "manager-dump.h"
48 #include "memory-util.h"
49 #include "missing_fs.h"
50 #include "missing_prctl.h"
51 #include "mkdir-label.h"
52 #include "namespace.h"
53 #include "parse-util.h"
54 #include "path-util.h"
55 #include "process-util.h"
56 #include "rlimit-util.h"
57 #include "rm-rf.h"
58 #include "seccomp-util.h"
59 #include "securebits-util.h"
60 #include "selinux-util.h"
61 #include "serialize.h"
62 #include "sort-util.h"
63 #include "special.h"
64 #include "stat-util.h"
65 #include "string-table.h"
66 #include "string-util.h"
67 #include "strv.h"
68 #include "syslog-util.h"
69 #include "terminal-util.h"
70 #include "tmpfile-util.h"
71 #include "umask-util.h"
72 #include "unit-serialize.h"
73 #include "user-util.h"
74 #include "utmp-wtmp.h"
75
76 static bool is_terminal_input(ExecInput i) {
77 return IN_SET(i,
78 EXEC_INPUT_TTY,
79 EXEC_INPUT_TTY_FORCE,
80 EXEC_INPUT_TTY_FAIL);
81 }
82
83 static bool is_terminal_output(ExecOutput o) {
84 return IN_SET(o,
85 EXEC_OUTPUT_TTY,
86 EXEC_OUTPUT_KMSG_AND_CONSOLE,
87 EXEC_OUTPUT_JOURNAL_AND_CONSOLE);
88 }
89
90 const char *exec_context_tty_path(const ExecContext *context) {
91 assert(context);
92
93 if (context->stdio_as_fds)
94 return NULL;
95
96 if (context->tty_path)
97 return context->tty_path;
98
99 return "/dev/console";
100 }
101
102 static void exec_context_determine_tty_size(
103 const ExecContext *context,
104 const char *tty_path,
105 unsigned *ret_rows,
106 unsigned *ret_cols) {
107
108 unsigned rows, cols;
109
110 assert(context);
111 assert(ret_rows);
112 assert(ret_cols);
113
114 if (!tty_path)
115 tty_path = exec_context_tty_path(context);
116
117 rows = context->tty_rows;
118 cols = context->tty_cols;
119
120 if (tty_path && (rows == UINT_MAX || cols == UINT_MAX))
121 (void) proc_cmdline_tty_size(
122 tty_path,
123 rows == UINT_MAX ? &rows : NULL,
124 cols == UINT_MAX ? &cols : NULL);
125
126 *ret_rows = rows;
127 *ret_cols = cols;
128 }
129
130 int exec_context_apply_tty_size(
131 const ExecContext *context,
132 int tty_fd,
133 const char *tty_path) {
134
135 unsigned rows, cols;
136
137 exec_context_determine_tty_size(context, tty_path, &rows, &cols);
138
139 return terminal_set_size_fd(tty_fd, tty_path, rows, cols);
140 }
141
142 void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) {
143 _cleanup_close_ int _fd = -EBADF, lock_fd = -EBADF;
144 int fd;
145
146 assert(context);
147
148 const char *path = exec_context_tty_path(context);
149
150 if (p && p->stdin_fd >= 0 && isatty_safe(p->stdin_fd))
151 fd = p->stdin_fd;
152 else if (path && (context->tty_path || is_terminal_input(context->std_input) ||
153 is_terminal_output(context->std_output) || is_terminal_output(context->std_error))) {
154 fd = _fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
155 if (fd < 0)
156 return (void) log_debug_errno(fd, "Failed to open terminal '%s', ignoring: %m", path);
157 } else
158 return; /* nothing to do */
159
160 /* Take a synchronization lock for the duration of the setup that we do here.
161 * systemd-vconsole-setup.service also takes the lock to avoid being interrupted. We open a new fd
162 * that will be closed automatically, and operate on it for convenience. */
163 lock_fd = lock_dev_console();
164 if (ERRNO_IS_NEG_PRIVILEGE(lock_fd))
165 log_debug_errno(lock_fd, "No privileges to lock /dev/console, proceeding without: %m");
166 else if (ERRNO_IS_NEG_DEVICE_ABSENT(lock_fd))
167 log_debug_errno(lock_fd, "Device /dev/console does not exist, proceeding without locking it: %m");
168 else if (lock_fd < 0)
169 return (void) log_debug_errno(lock_fd, "Failed to lock /dev/console: %m");
170
171 if (context->tty_vhangup)
172 (void) terminal_vhangup_fd(fd);
173
174 if (context->tty_reset)
175 (void) reset_terminal_fd(fd, /* switch_to_text= */ true);
176
177 (void) exec_context_apply_tty_size(context, fd, path);
178
179 if (context->tty_vt_disallocate && path)
180 (void) vt_disallocate(path);
181 }
182
183 bool exec_needs_network_namespace(const ExecContext *context) {
184 assert(context);
185
186 return context->private_network || context->network_namespace_path;
187 }
188
189 static bool exec_needs_ephemeral(const ExecContext *context) {
190 return (context->root_image || context->root_directory) && context->root_ephemeral;
191 }
192
193 bool exec_needs_ipc_namespace(const ExecContext *context) {
194 assert(context);
195
196 return context->private_ipc || context->ipc_namespace_path;
197 }
198
199 bool exec_needs_mount_namespace(
200 const ExecContext *context,
201 const ExecParameters *params,
202 const ExecRuntime *runtime) {
203
204 assert(context);
205
206 if (context->root_image)
207 return true;
208
209 if (!strv_isempty(context->read_write_paths) ||
210 !strv_isempty(context->read_only_paths) ||
211 !strv_isempty(context->inaccessible_paths) ||
212 !strv_isempty(context->exec_paths) ||
213 !strv_isempty(context->no_exec_paths))
214 return true;
215
216 if (context->n_bind_mounts > 0)
217 return true;
218
219 if (context->n_temporary_filesystems > 0)
220 return true;
221
222 if (context->n_mount_images > 0)
223 return true;
224
225 if (context->n_extension_images > 0)
226 return true;
227
228 if (!strv_isempty(context->extension_directories))
229 return true;
230
231 if (!IN_SET(context->mount_propagation_flag, 0, MS_SHARED))
232 return true;
233
234 if (context->private_tmp && runtime && runtime->shared && (runtime->shared->tmp_dir || runtime->shared->var_tmp_dir))
235 return true;
236
237 if (context->private_devices ||
238 context->private_mounts > 0 ||
239 (context->private_mounts < 0 && exec_needs_network_namespace(context)) ||
240 context->protect_system != PROTECT_SYSTEM_NO ||
241 context->protect_home != PROTECT_HOME_NO ||
242 context->protect_kernel_tunables ||
243 context->protect_kernel_modules ||
244 context->protect_kernel_logs ||
245 context->protect_control_groups ||
246 context->protect_proc != PROTECT_PROC_DEFAULT ||
247 context->proc_subset != PROC_SUBSET_ALL ||
248 exec_needs_ipc_namespace(context))
249 return true;
250
251 if (context->root_directory) {
252 if (exec_context_get_effective_mount_apivfs(context))
253 return true;
254
255 for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
256 if (params && !params->prefix[t])
257 continue;
258
259 if (context->directories[t].n_items > 0)
260 return true;
261 }
262 }
263
264 if (context->dynamic_user &&
265 (context->directories[EXEC_DIRECTORY_STATE].n_items > 0 ||
266 context->directories[EXEC_DIRECTORY_CACHE].n_items > 0 ||
267 context->directories[EXEC_DIRECTORY_LOGS].n_items > 0))
268 return true;
269
270 if (context->log_namespace)
271 return true;
272
273 return false;
274 }
275
276 bool exec_directory_is_private(const ExecContext *context, ExecDirectoryType type) {
277 assert(context);
278
279 if (!context->dynamic_user)
280 return false;
281
282 if (type == EXEC_DIRECTORY_CONFIGURATION)
283 return false;
284
285 if (type == EXEC_DIRECTORY_RUNTIME && context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO)
286 return false;
287
288 return true;
289 }
290
291 int exec_params_get_cgroup_path(
292 const ExecParameters *params,
293 const CGroupContext *c,
294 char **ret) {
295
296 const char *subgroup = NULL;
297 char *p;
298
299 assert(params);
300 assert(ret);
301
302 if (!params->cgroup_path)
303 return -EINVAL;
304
305 /* If we are called for a unit where cgroup delegation is on, and the payload created its own populated
306 * subcgroup (which we expect it to do, after all it asked for delegation), then we cannot place the control
307 * processes started after the main unit's process in the unit's main cgroup because it is now an inner one,
308 * and inner cgroups may not contain processes. Hence, if delegation is on, and this is a control process,
309 * let's use ".control" as subcgroup instead. Note that we do so only for ExecStartPost=, ExecReload=,
310 * ExecStop=, ExecStopPost=, i.e. for the commands where the main process is already forked. For ExecStartPre=
311 * this is not necessary, the cgroup is still empty. We distinguish these cases with the EXEC_CONTROL_CGROUP
312 * flag, which is only passed for the former statements, not for the latter. */
313
314 if (FLAGS_SET(params->flags, EXEC_CGROUP_DELEGATE) && (FLAGS_SET(params->flags, EXEC_CONTROL_CGROUP) || c->delegate_subgroup)) {
315 if (FLAGS_SET(params->flags, EXEC_IS_CONTROL))
316 subgroup = ".control";
317 else
318 subgroup = c->delegate_subgroup;
319 }
320
321 if (subgroup)
322 p = path_join(params->cgroup_path, subgroup);
323 else
324 p = strdup(params->cgroup_path);
325 if (!p)
326 return -ENOMEM;
327
328 *ret = p;
329 return !!subgroup;
330 }
331
332 bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c) {
333 assert(c);
334
335 return c->cpu_affinity_from_numa;
336 }
337
338 static void log_command_line(Unit *unit, const char *msg, const char *executable, char **argv) {
339 assert(unit);
340 assert(msg);
341 assert(executable);
342
343 if (!DEBUG_LOGGING)
344 return;
345
346 _cleanup_free_ char *cmdline = quote_command_line(argv, SHELL_ESCAPE_EMPTY);
347
348 log_unit_struct(unit, LOG_DEBUG,
349 "EXECUTABLE=%s", executable,
350 LOG_UNIT_MESSAGE(unit, "%s: %s", msg, strnull(cmdline)),
351 LOG_UNIT_INVOCATION_ID(unit));
352 }
353
354 static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l);
355
356 int exec_spawn(Unit *unit,
357 ExecCommand *command,
358 const ExecContext *context,
359 ExecParameters *params,
360 ExecRuntime *runtime,
361 const CGroupContext *cgroup_context,
362 PidRef *ret) {
363
364 char serialization_fd_number[DECIMAL_STR_MAX(int) + 1];
365 _cleanup_free_ char *subcgroup_path = NULL, *max_log_levels = NULL, *executor_path = NULL;
366 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
367 _cleanup_fdset_free_ FDSet *fdset = NULL;
368 _cleanup_fclose_ FILE *f = NULL;
369 dual_timestamp start_timestamp;
370 int r;
371
372 assert(unit);
373 assert(unit->manager);
374 assert(unit->manager->executor_fd >= 0);
375 assert(command);
376 assert(context);
377 assert(params);
378 assert(!params->fds || FLAGS_SET(params->flags, EXEC_PASS_FDS));
379 assert(params->fds || (params->n_socket_fds + params->n_storage_fds == 0));
380 assert(!params->files_env); /* We fill this field, ensure it comes NULL-initialized to us */
381 assert(ret);
382
383 LOG_CONTEXT_PUSH_UNIT(unit);
384
385 r = exec_context_load_environment(unit, context, &params->files_env);
386 if (r < 0)
387 return log_unit_error_errno(unit, r, "Failed to load environment files: %m");
388
389 /* We won't know the real executable path until we create the mount namespace in the child, but we
390 want to log from the parent, so we use the possibly inaccurate path here. */
391 log_command_line(unit, "About to execute", command->path, command->argv);
392
393 if (params->cgroup_path) {
394 r = exec_params_get_cgroup_path(params, cgroup_context, &subcgroup_path);
395 if (r < 0)
396 return log_unit_error_errno(unit, r, "Failed to acquire subcgroup path: %m");
397 if (r > 0) {
398 /* If there's a subcgroup, then let's create it here now (the main cgroup was already
399 * realized by the unit logic) */
400
401 r = cg_create(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path);
402 if (r < 0)
403 return log_unit_error_errno(unit, r, "Failed to create subcgroup '%s': %m", subcgroup_path);
404 }
405 }
406
407 /* In order to avoid copy-on-write traps and OOM-kills when pid1's memory.current is above the
408 * child's memory.max, serialize all the state needed to start the unit, and pass it to the
409 * systemd-executor binary. clone() with CLONE_VM + CLONE_VFORK will pause the parent until the exec
410 * and ensure all memory is shared. The child immediately execs the new binary so the delay should
411 * be minimal. If glibc 2.39 is available pidfd_spawn() is used in order to get a race-free pid fd
412 * and to clone directly into the target cgroup (if we booted with cgroupv2). */
413
414 r = open_serialization_file("sd-executor-state", &f);
415 if (r < 0)
416 return log_unit_error_errno(unit, r, "Failed to open serialization stream: %m");
417
418 fdset = fdset_new();
419 if (!fdset)
420 return log_oom();
421
422 r = exec_serialize_invocation(f, fdset, context, command, params, runtime, cgroup_context);
423 if (r < 0)
424 return log_unit_error_errno(unit, r, "Failed to serialize parameters: %m");
425
426 if (fseeko(f, 0, SEEK_SET) < 0)
427 return log_unit_error_errno(unit, errno, "Failed to reseek on serialization stream: %m");
428
429 r = fd_cloexec(fileno(f), false);
430 if (r < 0)
431 return log_unit_error_errno(unit, r, "Failed to set O_CLOEXEC on serialization fd: %m");
432
433 r = fdset_cloexec(fdset, false);
434 if (r < 0)
435 return log_unit_error_errno(unit, r, "Failed to set O_CLOEXEC on serialized fds: %m");
436
437 /* If LogLevelMax= is specified, then let's use the specified log level at the beginning of the
438 * executor process. To achieve that the specified log level is passed as an argument, rather than
439 * the one for the manager process. */
440 r = log_max_levels_to_string(context->log_level_max >= 0 ? context->log_level_max : log_get_max_level(), &max_log_levels);
441 if (r < 0)
442 return log_unit_error_errno(unit, r, "Failed to convert max log levels to string: %m");
443
444 r = fd_get_path(unit->manager->executor_fd, &executor_path);
445 if (r < 0)
446 return log_unit_error_errno(unit, r, "Failed to get executor path from fd: %m");
447
448 xsprintf(serialization_fd_number, "%i", fileno(f));
449
450 /* Record the start timestamp before we fork so that it is guaranteed to be earlier than the
451 * handoff timestamp. */
452 dual_timestamp_now(&start_timestamp);
453
454 /* The executor binary is pinned, to avoid compatibility problems during upgrades. */
455 r = posix_spawn_wrapper(
456 FORMAT_PROC_FD_PATH(unit->manager->executor_fd),
457 STRV_MAKE(executor_path,
458 "--deserialize", serialization_fd_number,
459 "--log-level", max_log_levels,
460 "--log-target", log_target_to_string(manager_get_executor_log_target(unit->manager))),
461 environ,
462 cg_unified() > 0 ? subcgroup_path : NULL,
463 &pidref);
464 if (r == -EUCLEAN && subcgroup_path)
465 return log_unit_error_errno(unit, r,
466 "Failed to spawn process into cgroup '%s', because the cgroup "
467 "or one of its parents or siblings is in the threaded mode.",
468 subcgroup_path);
469 if (r < 0)
470 return log_unit_error_errno(unit, r, "Failed to spawn executor: %m");
471 /* We add the new process to the cgroup both in the child (so that we can be sure that no user code is ever
472 * executed outside of the cgroup) and in the parent (so that we can be sure that when we kill the cgroup the
473 * process will be killed too). */
474 if (r == 0 && subcgroup_path)
475 (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path, pidref.pid);
476 /* r > 0: Already in the right cgroup thanks to CLONE_INTO_CGROUP */
477
478 log_unit_debug(unit, "Forked %s as " PID_FMT " (%s CLONE_INTO_CGROUP)",
479 command->path, pidref.pid, r > 0 ? "via" : "without");
480
481 exec_status_start(&command->exec_status, pidref.pid, &start_timestamp);
482
483 *ret = TAKE_PIDREF(pidref);
484 return 0;
485 }
486
487 void exec_context_init(ExecContext *c) {
488 assert(c);
489
490 /* When initializing a bool member to 'true', make sure to serialize in execute-serialize.c using
491 * serialize_bool() instead of serialize_bool_elide(). */
492
493 *c = (ExecContext) {
494 .umask = 0022,
495 .ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO,
496 .cpu_sched_policy = SCHED_OTHER,
497 .syslog_priority = LOG_DAEMON|LOG_INFO,
498 .syslog_level_prefix = true,
499 .ignore_sigpipe = true,
500 .timer_slack_nsec = NSEC_INFINITY,
501 .personality = PERSONALITY_INVALID,
502 .timeout_clean_usec = USEC_INFINITY,
503 .capability_bounding_set = CAP_MASK_UNSET,
504 .restrict_namespaces = NAMESPACE_FLAGS_INITIAL,
505 .log_level_max = -1,
506 #if HAVE_SECCOMP
507 .syscall_errno = SECCOMP_ERROR_NUMBER_KILL,
508 #endif
509 .tty_rows = UINT_MAX,
510 .tty_cols = UINT_MAX,
511 .private_mounts = -1,
512 .mount_apivfs = -1,
513 .memory_ksm = -1,
514 .set_login_environment = -1,
515 };
516
517 FOREACH_ARRAY(d, c->directories, _EXEC_DIRECTORY_TYPE_MAX)
518 d->mode = 0755;
519
520 numa_policy_reset(&c->numa_policy);
521
522 assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL);
523 }
524
525 void exec_context_done(ExecContext *c) {
526 assert(c);
527
528 c->environment = strv_free(c->environment);
529 c->environment_files = strv_free(c->environment_files);
530 c->pass_environment = strv_free(c->pass_environment);
531 c->unset_environment = strv_free(c->unset_environment);
532
533 rlimit_free_all(c->rlimit);
534
535 for (size_t l = 0; l < 3; l++) {
536 c->stdio_fdname[l] = mfree(c->stdio_fdname[l]);
537 c->stdio_file[l] = mfree(c->stdio_file[l]);
538 }
539
540 c->working_directory = mfree(c->working_directory);
541 c->root_directory = mfree(c->root_directory);
542 c->root_image = mfree(c->root_image);
543 c->root_image_options = mount_options_free_all(c->root_image_options);
544 c->root_hash = mfree(c->root_hash);
545 c->root_hash_size = 0;
546 c->root_hash_path = mfree(c->root_hash_path);
547 c->root_hash_sig = mfree(c->root_hash_sig);
548 c->root_hash_sig_size = 0;
549 c->root_hash_sig_path = mfree(c->root_hash_sig_path);
550 c->root_verity = mfree(c->root_verity);
551 c->extension_images = mount_image_free_many(c->extension_images, &c->n_extension_images);
552 c->extension_directories = strv_free(c->extension_directories);
553 c->tty_path = mfree(c->tty_path);
554 c->syslog_identifier = mfree(c->syslog_identifier);
555 c->user = mfree(c->user);
556 c->group = mfree(c->group);
557
558 c->supplementary_groups = strv_free(c->supplementary_groups);
559
560 c->pam_name = mfree(c->pam_name);
561
562 c->read_only_paths = strv_free(c->read_only_paths);
563 c->read_write_paths = strv_free(c->read_write_paths);
564 c->inaccessible_paths = strv_free(c->inaccessible_paths);
565 c->exec_paths = strv_free(c->exec_paths);
566 c->no_exec_paths = strv_free(c->no_exec_paths);
567 c->exec_search_path = strv_free(c->exec_search_path);
568
569 bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
570 c->bind_mounts = NULL;
571 c->n_bind_mounts = 0;
572 temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems);
573 c->temporary_filesystems = NULL;
574 c->n_temporary_filesystems = 0;
575 c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images);
576
577 cpu_set_reset(&c->cpu_set);
578 numa_policy_reset(&c->numa_policy);
579
580 c->utmp_id = mfree(c->utmp_id);
581 c->selinux_context = mfree(c->selinux_context);
582 c->apparmor_profile = mfree(c->apparmor_profile);
583 c->smack_process_label = mfree(c->smack_process_label);
584
585 c->restrict_filesystems = set_free_free(c->restrict_filesystems);
586
587 c->syscall_filter = hashmap_free(c->syscall_filter);
588 c->syscall_archs = set_free(c->syscall_archs);
589 c->address_families = set_free(c->address_families);
590
591 FOREACH_ARRAY(d, c->directories, _EXEC_DIRECTORY_TYPE_MAX)
592 exec_directory_done(d);
593
594 c->log_level_max = -1;
595
596 exec_context_free_log_extra_fields(c);
597 c->log_filter_allowed_patterns = set_free_free(c->log_filter_allowed_patterns);
598 c->log_filter_denied_patterns = set_free_free(c->log_filter_denied_patterns);
599
600 c->log_ratelimit_interval_usec = 0;
601 c->log_ratelimit_burst = 0;
602
603 c->stdin_data = mfree(c->stdin_data);
604 c->stdin_data_size = 0;
605
606 c->network_namespace_path = mfree(c->network_namespace_path);
607 c->ipc_namespace_path = mfree(c->ipc_namespace_path);
608
609 c->log_namespace = mfree(c->log_namespace);
610
611 c->load_credentials = hashmap_free(c->load_credentials);
612 c->set_credentials = hashmap_free(c->set_credentials);
613 c->import_credentials = set_free_free(c->import_credentials);
614
615 c->root_image_policy = image_policy_free(c->root_image_policy);
616 c->mount_image_policy = image_policy_free(c->mount_image_policy);
617 c->extension_image_policy = image_policy_free(c->extension_image_policy);
618 }
619
620 int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_prefix) {
621 assert(c);
622
623 if (!runtime_prefix)
624 return 0;
625
626 FOREACH_ARRAY(i, c->directories[EXEC_DIRECTORY_RUNTIME].items, c->directories[EXEC_DIRECTORY_RUNTIME].n_items) {
627 _cleanup_free_ char *p = NULL;
628
629 if (exec_directory_is_private(c, EXEC_DIRECTORY_RUNTIME))
630 p = path_join(runtime_prefix, "private", i->path);
631 else
632 p = path_join(runtime_prefix, i->path);
633 if (!p)
634 return -ENOMEM;
635
636 /* We execute this synchronously, since we need to be sure this is gone when we start the
637 * service next. */
638 (void) rm_rf(p, REMOVE_ROOT);
639
640 STRV_FOREACH(symlink, i->symlinks) {
641 _cleanup_free_ char *symlink_abs = NULL;
642
643 if (exec_directory_is_private(c, EXEC_DIRECTORY_RUNTIME))
644 symlink_abs = path_join(runtime_prefix, "private", *symlink);
645 else
646 symlink_abs = path_join(runtime_prefix, *symlink);
647 if (!symlink_abs)
648 return -ENOMEM;
649
650 (void) unlink(symlink_abs);
651 }
652 }
653
654 return 0;
655 }
656
657 int exec_context_destroy_mount_ns_dir(Unit *u) {
658 _cleanup_free_ char *p = NULL;
659
660 if (!u || !MANAGER_IS_SYSTEM(u->manager))
661 return 0;
662
663 p = path_join("/run/systemd/propagate/", u->id);
664 if (!p)
665 return -ENOMEM;
666
667 /* This is only filled transiently (see mount_in_namespace()), should be empty or even non-existent*/
668 if (rmdir(p) < 0 && errno != ENOENT)
669 log_unit_debug_errno(u, errno, "Unable to remove propagation dir '%s', ignoring: %m", p);
670
671 return 0;
672 }
673
674 void exec_command_done(ExecCommand *c) {
675 assert(c);
676
677 c->path = mfree(c->path);
678 c->argv = strv_free(c->argv);
679 }
680
681 void exec_command_done_array(ExecCommand *c, size_t n) {
682 FOREACH_ARRAY(i, c, n)
683 exec_command_done(i);
684 }
685
686 ExecCommand* exec_command_free(ExecCommand *c) {
687 if (!c)
688 return NULL;
689
690 exec_command_done(c);
691 return mfree(c);
692 }
693
694 ExecCommand* exec_command_free_list(ExecCommand *c) {
695 ExecCommand *i;
696
697 while ((i = LIST_POP(command, c)))
698 exec_command_free(i);
699
700 return NULL;
701 }
702
703 void exec_command_free_array(ExecCommand **c, size_t n) {
704 FOREACH_ARRAY(i, c, n)
705 *i = exec_command_free_list(*i);
706 }
707
708 void exec_command_reset_status_array(ExecCommand *c, size_t n) {
709 FOREACH_ARRAY(i, c, n)
710 exec_status_reset(&i->exec_status);
711 }
712
713 void exec_command_reset_status_list_array(ExecCommand **c, size_t n) {
714 FOREACH_ARRAY(i, c, n)
715 LIST_FOREACH(command, z, *i)
716 exec_status_reset(&z->exec_status);
717 }
718
719 typedef struct InvalidEnvInfo {
720 const Unit *unit;
721 const char *path;
722 } InvalidEnvInfo;
723
724 static void invalid_env(const char *p, void *userdata) {
725 InvalidEnvInfo *info = userdata;
726
727 log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path);
728 }
729
730 const char* exec_context_fdname(const ExecContext *c, int fd_index) {
731 assert(c);
732
733 switch (fd_index) {
734
735 case STDIN_FILENO:
736 if (c->std_input != EXEC_INPUT_NAMED_FD)
737 return NULL;
738
739 return c->stdio_fdname[STDIN_FILENO] ?: "stdin";
740
741 case STDOUT_FILENO:
742 if (c->std_output != EXEC_OUTPUT_NAMED_FD)
743 return NULL;
744
745 return c->stdio_fdname[STDOUT_FILENO] ?: "stdout";
746
747 case STDERR_FILENO:
748 if (c->std_error != EXEC_OUTPUT_NAMED_FD)
749 return NULL;
750
751 return c->stdio_fdname[STDERR_FILENO] ?: "stderr";
752
753 default:
754 return NULL;
755 }
756 }
757
758 static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***ret) {
759 _cleanup_strv_free_ char **v = NULL;
760 int r;
761
762 assert(c);
763 assert(ret);
764
765 STRV_FOREACH(i, c->environment_files) {
766 _cleanup_globfree_ glob_t pglob = {};
767 bool ignore = false;
768 char *fn = *i;
769
770 if (fn[0] == '-') {
771 ignore = true;
772 fn++;
773 }
774
775 if (!path_is_absolute(fn)) {
776 if (ignore)
777 continue;
778 return -EINVAL;
779 }
780
781 /* Filename supports globbing, take all matching files */
782 r = safe_glob(fn, 0, &pglob);
783 if (r < 0) {
784 if (ignore)
785 continue;
786 return r;
787 }
788
789 /* When we don't match anything, -ENOENT should be returned */
790 assert(pglob.gl_pathc > 0);
791
792 FOREACH_ARRAY(path, pglob.gl_pathv, pglob.gl_pathc) {
793 _cleanup_strv_free_ char **p = NULL;
794
795 r = load_env_file(NULL, *path, &p);
796 if (r < 0) {
797 if (ignore)
798 continue;
799 return r;
800 }
801
802 /* Log invalid environment variables with filename */
803 if (p) {
804 InvalidEnvInfo info = {
805 .unit = unit,
806 .path = *path,
807 };
808
809 p = strv_env_clean_with_callback(p, invalid_env, &info);
810 }
811
812 if (!v)
813 v = TAKE_PTR(p);
814 else {
815 char **m = strv_env_merge(v, p);
816 if (!m)
817 return -ENOMEM;
818
819 strv_free_and_replace(v, m);
820 }
821 }
822 }
823
824 *ret = TAKE_PTR(v);
825
826 return 0;
827 }
828
829 static bool tty_may_match_dev_console(const char *tty) {
830 _cleanup_free_ char *resolved = NULL;
831
832 if (!tty)
833 return true;
834
835 tty = skip_dev_prefix(tty);
836
837 /* trivial identity? */
838 if (streq(tty, "console"))
839 return true;
840
841 if (resolve_dev_console(&resolved) < 0)
842 return true; /* if we could not resolve, assume it may */
843
844 /* "tty0" means the active VC, so it may be the same sometimes */
845 return path_equal(resolved, tty) || (streq(resolved, "tty0") && tty_is_vc(tty));
846 }
847
848 static bool exec_context_may_touch_tty(const ExecContext *ec) {
849 assert(ec);
850
851 return ec->tty_reset ||
852 ec->tty_vhangup ||
853 ec->tty_vt_disallocate ||
854 is_terminal_input(ec->std_input) ||
855 is_terminal_output(ec->std_output) ||
856 is_terminal_output(ec->std_error);
857 }
858
859 bool exec_context_may_touch_console(const ExecContext *ec) {
860
861 return exec_context_may_touch_tty(ec) &&
862 tty_may_match_dev_console(exec_context_tty_path(ec));
863 }
864
865 static void strv_fprintf(FILE *f, char **l) {
866 assert(f);
867
868 STRV_FOREACH(g, l)
869 fprintf(f, " %s", *g);
870 }
871
872 static void strv_dump(FILE* f, const char *prefix, const char *name, char **strv) {
873 assert(f);
874 assert(prefix);
875 assert(name);
876
877 if (!strv_isempty(strv)) {
878 fprintf(f, "%s%s:", prefix, name);
879 strv_fprintf(f, strv);
880 fputs("\n", f);
881 }
882 }
883
884 void exec_params_dump(const ExecParameters *p, FILE* f, const char *prefix) {
885 assert(p);
886 assert(f);
887
888 prefix = strempty(prefix);
889
890 fprintf(f,
891 "%sRuntimeScope: %s\n"
892 "%sExecFlags: %u\n"
893 "%sSELinuxContextNetwork: %s\n"
894 "%sCgroupSupportedMask: %u\n"
895 "%sCgroupPath: %s\n"
896 "%sCrededentialsDirectory: %s\n"
897 "%sEncryptedCredentialsDirectory: %s\n"
898 "%sConfirmSpawn: %s\n"
899 "%sShallConfirmSpawn: %s\n"
900 "%sWatchdogUSec: " USEC_FMT "\n"
901 "%sNotifySocket: %s\n"
902 "%sFallbackSmackProcessLabel: %s\n",
903 prefix, runtime_scope_to_string(p->runtime_scope),
904 prefix, p->flags,
905 prefix, yes_no(p->selinux_context_net),
906 prefix, p->cgroup_supported,
907 prefix, p->cgroup_path,
908 prefix, strempty(p->received_credentials_directory),
909 prefix, strempty(p->received_encrypted_credentials_directory),
910 prefix, strempty(p->confirm_spawn),
911 prefix, yes_no(p->shall_confirm_spawn),
912 prefix, p->watchdog_usec,
913 prefix, strempty(p->notify_socket),
914 prefix, strempty(p->fallback_smack_process_label));
915
916 strv_dump(f, prefix, "FdNames", p->fd_names);
917 strv_dump(f, prefix, "Environment", p->environment);
918 strv_dump(f, prefix, "Prefix", p->prefix);
919
920 LIST_FOREACH(open_files, file, p->open_files)
921 fprintf(f, "%sOpenFile: %s %s", prefix, file->path, open_file_flags_to_string(file->flags));
922
923 strv_dump(f, prefix, "FilesEnv", p->files_env);
924 }
925
926 void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
927 int r;
928
929 assert(c);
930 assert(f);
931
932 prefix = strempty(prefix);
933
934 fprintf(f,
935 "%sUMask: %04o\n"
936 "%sWorkingDirectory: %s\n"
937 "%sRootDirectory: %s\n"
938 "%sRootEphemeral: %s\n"
939 "%sNonBlocking: %s\n"
940 "%sPrivateTmp: %s\n"
941 "%sPrivateDevices: %s\n"
942 "%sProtectKernelTunables: %s\n"
943 "%sProtectKernelModules: %s\n"
944 "%sProtectKernelLogs: %s\n"
945 "%sProtectClock: %s\n"
946 "%sProtectControlGroups: %s\n"
947 "%sPrivateNetwork: %s\n"
948 "%sPrivateUsers: %s\n"
949 "%sProtectHome: %s\n"
950 "%sProtectSystem: %s\n"
951 "%sMountAPIVFS: %s\n"
952 "%sIgnoreSIGPIPE: %s\n"
953 "%sMemoryDenyWriteExecute: %s\n"
954 "%sRestrictRealtime: %s\n"
955 "%sRestrictSUIDSGID: %s\n"
956 "%sKeyringMode: %s\n"
957 "%sProtectHostname: %s\n"
958 "%sProtectProc: %s\n"
959 "%sProcSubset: %s\n",
960 prefix, c->umask,
961 prefix, empty_to_root(c->working_directory),
962 prefix, empty_to_root(c->root_directory),
963 prefix, yes_no(c->root_ephemeral),
964 prefix, yes_no(c->non_blocking),
965 prefix, yes_no(c->private_tmp),
966 prefix, yes_no(c->private_devices),
967 prefix, yes_no(c->protect_kernel_tunables),
968 prefix, yes_no(c->protect_kernel_modules),
969 prefix, yes_no(c->protect_kernel_logs),
970 prefix, yes_no(c->protect_clock),
971 prefix, yes_no(c->protect_control_groups),
972 prefix, yes_no(c->private_network),
973 prefix, yes_no(c->private_users),
974 prefix, protect_home_to_string(c->protect_home),
975 prefix, protect_system_to_string(c->protect_system),
976 prefix, yes_no(exec_context_get_effective_mount_apivfs(c)),
977 prefix, yes_no(c->ignore_sigpipe),
978 prefix, yes_no(c->memory_deny_write_execute),
979 prefix, yes_no(c->restrict_realtime),
980 prefix, yes_no(c->restrict_suid_sgid),
981 prefix, exec_keyring_mode_to_string(c->keyring_mode),
982 prefix, yes_no(c->protect_hostname),
983 prefix, protect_proc_to_string(c->protect_proc),
984 prefix, proc_subset_to_string(c->proc_subset));
985
986 if (c->set_login_environment >= 0)
987 fprintf(f, "%sSetLoginEnvironment: %s\n", prefix, yes_no(c->set_login_environment > 0));
988
989 if (c->root_image)
990 fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
991
992 if (c->root_image_options) {
993 fprintf(f, "%sRootImageOptions:", prefix);
994 LIST_FOREACH(mount_options, o, c->root_image_options)
995 if (!isempty(o->options))
996 fprintf(f, " %s:%s",
997 partition_designator_to_string(o->partition_designator),
998 o->options);
999 fprintf(f, "\n");
1000 }
1001
1002 if (c->root_hash) {
1003 _cleanup_free_ char *encoded = NULL;
1004 encoded = hexmem(c->root_hash, c->root_hash_size);
1005 if (encoded)
1006 fprintf(f, "%sRootHash: %s\n", prefix, encoded);
1007 }
1008
1009 if (c->root_hash_path)
1010 fprintf(f, "%sRootHash: %s\n", prefix, c->root_hash_path);
1011
1012 if (c->root_hash_sig) {
1013 _cleanup_free_ char *encoded = NULL;
1014 ssize_t len;
1015 len = base64mem(c->root_hash_sig, c->root_hash_sig_size, &encoded);
1016 if (len)
1017 fprintf(f, "%sRootHashSignature: base64:%s\n", prefix, encoded);
1018 }
1019
1020 if (c->root_hash_sig_path)
1021 fprintf(f, "%sRootHashSignature: %s\n", prefix, c->root_hash_sig_path);
1022
1023 if (c->root_verity)
1024 fprintf(f, "%sRootVerity: %s\n", prefix, c->root_verity);
1025
1026 STRV_FOREACH(e, c->environment)
1027 fprintf(f, "%sEnvironment: %s\n", prefix, *e);
1028
1029 STRV_FOREACH(e, c->environment_files)
1030 fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
1031
1032 STRV_FOREACH(e, c->pass_environment)
1033 fprintf(f, "%sPassEnvironment: %s\n", prefix, *e);
1034
1035 STRV_FOREACH(e, c->unset_environment)
1036 fprintf(f, "%sUnsetEnvironment: %s\n", prefix, *e);
1037
1038 fprintf(f, "%sRuntimeDirectoryPreserve: %s\n", prefix, exec_preserve_mode_to_string(c->runtime_directory_preserve_mode));
1039
1040 for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) {
1041 fprintf(f, "%s%sMode: %04o\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].mode);
1042
1043 for (size_t i = 0; i < c->directories[dt].n_items; i++) {
1044 fprintf(f, "%s%s: %s\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].items[i].path);
1045
1046 STRV_FOREACH(d, c->directories[dt].items[i].symlinks)
1047 fprintf(f, "%s%s: %s:%s\n", prefix, exec_directory_type_symlink_to_string(dt), c->directories[dt].items[i].path, *d);
1048 }
1049 }
1050
1051 fprintf(f, "%sTimeoutCleanSec: %s\n", prefix, FORMAT_TIMESPAN(c->timeout_clean_usec, USEC_PER_SEC));
1052
1053 if (c->memory_ksm >= 0)
1054 fprintf(f, "%sMemoryKSM: %s\n", prefix, yes_no(c->memory_ksm > 0));
1055
1056 if (c->nice_set)
1057 fprintf(f, "%sNice: %i\n", prefix, c->nice);
1058
1059 if (c->oom_score_adjust_set)
1060 fprintf(f, "%sOOMScoreAdjust: %i\n", prefix, c->oom_score_adjust);
1061
1062 if (c->coredump_filter_set)
1063 fprintf(f, "%sCoredumpFilter: 0x%"PRIx64"\n", prefix, c->coredump_filter);
1064
1065 for (unsigned i = 0; i < RLIM_NLIMITS; i++)
1066 if (c->rlimit[i]) {
1067 fprintf(f, "%sLimit%s: " RLIM_FMT "\n",
1068 prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
1069 fprintf(f, "%sLimit%sSoft: " RLIM_FMT "\n",
1070 prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur);
1071 }
1072
1073 if (c->ioprio_set) {
1074 _cleanup_free_ char *class_str = NULL;
1075
1076 r = ioprio_class_to_string_alloc(ioprio_prio_class(c->ioprio), &class_str);
1077 if (r >= 0)
1078 fprintf(f, "%sIOSchedulingClass: %s\n", prefix, class_str);
1079
1080 fprintf(f, "%sIOPriority: %d\n", prefix, ioprio_prio_data(c->ioprio));
1081 }
1082
1083 if (c->cpu_sched_set) {
1084 _cleanup_free_ char *policy_str = NULL;
1085
1086 r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
1087 if (r >= 0)
1088 fprintf(f, "%sCPUSchedulingPolicy: %s\n", prefix, policy_str);
1089
1090 fprintf(f,
1091 "%sCPUSchedulingPriority: %i\n"
1092 "%sCPUSchedulingResetOnFork: %s\n",
1093 prefix, c->cpu_sched_priority,
1094 prefix, yes_no(c->cpu_sched_reset_on_fork));
1095 }
1096
1097 if (c->cpu_set.set) {
1098 _cleanup_free_ char *affinity = NULL;
1099
1100 affinity = cpu_set_to_range_string(&c->cpu_set);
1101 fprintf(f, "%sCPUAffinity: %s\n", prefix, affinity);
1102 }
1103
1104 if (mpol_is_valid(numa_policy_get_type(&c->numa_policy))) {
1105 _cleanup_free_ char *nodes = NULL;
1106
1107 nodes = cpu_set_to_range_string(&c->numa_policy.nodes);
1108 fprintf(f, "%sNUMAPolicy: %s\n", prefix, mpol_to_string(numa_policy_get_type(&c->numa_policy)));
1109 fprintf(f, "%sNUMAMask: %s\n", prefix, strnull(nodes));
1110 }
1111
1112 if (c->timer_slack_nsec != NSEC_INFINITY)
1113 fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, c->timer_slack_nsec);
1114
1115 fprintf(f,
1116 "%sStandardInput: %s\n"
1117 "%sStandardOutput: %s\n"
1118 "%sStandardError: %s\n",
1119 prefix, exec_input_to_string(c->std_input),
1120 prefix, exec_output_to_string(c->std_output),
1121 prefix, exec_output_to_string(c->std_error));
1122
1123 if (c->std_input == EXEC_INPUT_NAMED_FD)
1124 fprintf(f, "%sStandardInputFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDIN_FILENO]);
1125 if (c->std_output == EXEC_OUTPUT_NAMED_FD)
1126 fprintf(f, "%sStandardOutputFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDOUT_FILENO]);
1127 if (c->std_error == EXEC_OUTPUT_NAMED_FD)
1128 fprintf(f, "%sStandardErrorFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDERR_FILENO]);
1129
1130 if (c->std_input == EXEC_INPUT_FILE)
1131 fprintf(f, "%sStandardInputFile: %s\n", prefix, c->stdio_file[STDIN_FILENO]);
1132 if (c->std_output == EXEC_OUTPUT_FILE)
1133 fprintf(f, "%sStandardOutputFile: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
1134 if (c->std_output == EXEC_OUTPUT_FILE_APPEND)
1135 fprintf(f, "%sStandardOutputFileToAppend: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
1136 if (c->std_output == EXEC_OUTPUT_FILE_TRUNCATE)
1137 fprintf(f, "%sStandardOutputFileToTruncate: %s\n", prefix, c->stdio_file[STDOUT_FILENO]);
1138 if (c->std_error == EXEC_OUTPUT_FILE)
1139 fprintf(f, "%sStandardErrorFile: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
1140 if (c->std_error == EXEC_OUTPUT_FILE_APPEND)
1141 fprintf(f, "%sStandardErrorFileToAppend: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
1142 if (c->std_error == EXEC_OUTPUT_FILE_TRUNCATE)
1143 fprintf(f, "%sStandardErrorFileToTruncate: %s\n", prefix, c->stdio_file[STDERR_FILENO]);
1144
1145 if (c->tty_path)
1146 fprintf(f,
1147 "%sTTYPath: %s\n"
1148 "%sTTYReset: %s\n"
1149 "%sTTYVHangup: %s\n"
1150 "%sTTYVTDisallocate: %s\n"
1151 "%sTTYRows: %u\n"
1152 "%sTTYColumns: %u\n",
1153 prefix, c->tty_path,
1154 prefix, yes_no(c->tty_reset),
1155 prefix, yes_no(c->tty_vhangup),
1156 prefix, yes_no(c->tty_vt_disallocate),
1157 prefix, c->tty_rows,
1158 prefix, c->tty_cols);
1159
1160 if (IN_SET(c->std_output,
1161 EXEC_OUTPUT_KMSG,
1162 EXEC_OUTPUT_JOURNAL,
1163 EXEC_OUTPUT_KMSG_AND_CONSOLE,
1164 EXEC_OUTPUT_JOURNAL_AND_CONSOLE) ||
1165 IN_SET(c->std_error,
1166 EXEC_OUTPUT_KMSG,
1167 EXEC_OUTPUT_JOURNAL,
1168 EXEC_OUTPUT_KMSG_AND_CONSOLE,
1169 EXEC_OUTPUT_JOURNAL_AND_CONSOLE)) {
1170
1171 _cleanup_free_ char *fac_str = NULL, *lvl_str = NULL;
1172
1173 r = log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
1174 if (r >= 0)
1175 fprintf(f, "%sSyslogFacility: %s\n", prefix, fac_str);
1176
1177 r = log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
1178 if (r >= 0)
1179 fprintf(f, "%sSyslogLevel: %s\n", prefix, lvl_str);
1180 }
1181
1182 if (c->log_level_max >= 0) {
1183 _cleanup_free_ char *t = NULL;
1184
1185 (void) log_level_to_string_alloc(c->log_level_max, &t);
1186
1187 fprintf(f, "%sLogLevelMax: %s\n", prefix, strna(t));
1188 }
1189
1190 if (c->log_ratelimit_interval_usec > 0)
1191 fprintf(f,
1192 "%sLogRateLimitIntervalSec: %s\n",
1193 prefix, FORMAT_TIMESPAN(c->log_ratelimit_interval_usec, USEC_PER_SEC));
1194
1195 if (c->log_ratelimit_burst > 0)
1196 fprintf(f, "%sLogRateLimitBurst: %u\n", prefix, c->log_ratelimit_burst);
1197
1198 if (!set_isempty(c->log_filter_allowed_patterns) || !set_isempty(c->log_filter_denied_patterns)) {
1199 fprintf(f, "%sLogFilterPatterns:", prefix);
1200
1201 char *pattern;
1202 SET_FOREACH(pattern, c->log_filter_allowed_patterns)
1203 fprintf(f, " %s", pattern);
1204 SET_FOREACH(pattern, c->log_filter_denied_patterns)
1205 fprintf(f, " ~%s", pattern);
1206 fputc('\n', f);
1207 }
1208
1209 FOREACH_ARRAY(field, c->log_extra_fields, c->n_log_extra_fields) {
1210 fprintf(f, "%sLogExtraFields: ", prefix);
1211 fwrite(field->iov_base, 1, field->iov_len, f);
1212 fputc('\n', f);
1213 }
1214
1215 if (c->log_namespace)
1216 fprintf(f, "%sLogNamespace: %s\n", prefix, c->log_namespace);
1217
1218 if (c->secure_bits) {
1219 _cleanup_free_ char *str = NULL;
1220
1221 r = secure_bits_to_string_alloc(c->secure_bits, &str);
1222 if (r >= 0)
1223 fprintf(f, "%sSecure Bits: %s\n", prefix, str);
1224 }
1225
1226 if (c->capability_bounding_set != CAP_MASK_UNSET) {
1227 _cleanup_free_ char *str = NULL;
1228
1229 r = capability_set_to_string(c->capability_bounding_set, &str);
1230 if (r >= 0)
1231 fprintf(f, "%sCapabilityBoundingSet: %s\n", prefix, str);
1232 }
1233
1234 if (c->capability_ambient_set != 0) {
1235 _cleanup_free_ char *str = NULL;
1236
1237 r = capability_set_to_string(c->capability_ambient_set, &str);
1238 if (r >= 0)
1239 fprintf(f, "%sAmbientCapabilities: %s\n", prefix, str);
1240 }
1241
1242 if (c->user)
1243 fprintf(f, "%sUser: %s\n", prefix, c->user);
1244 if (c->group)
1245 fprintf(f, "%sGroup: %s\n", prefix, c->group);
1246
1247 fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user));
1248
1249 strv_dump(f, prefix, "SupplementaryGroups", c->supplementary_groups);
1250
1251 if (c->pam_name)
1252 fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
1253
1254 strv_dump(f, prefix, "ReadWritePaths", c->read_write_paths);
1255 strv_dump(f, prefix, "ReadOnlyPaths", c->read_only_paths);
1256 strv_dump(f, prefix, "InaccessiblePaths", c->inaccessible_paths);
1257 strv_dump(f, prefix, "ExecPaths", c->exec_paths);
1258 strv_dump(f, prefix, "NoExecPaths", c->no_exec_paths);
1259 strv_dump(f, prefix, "ExecSearchPath", c->exec_search_path);
1260
1261 FOREACH_ARRAY(mount, c->bind_mounts, c->n_bind_mounts)
1262 fprintf(f, "%s%s: %s%s:%s:%s\n", prefix,
1263 mount->read_only ? "BindReadOnlyPaths" : "BindPaths",
1264 mount->ignore_enoent ? "-": "",
1265 mount->source,
1266 mount->destination,
1267 mount->recursive ? "rbind" : "norbind");
1268
1269 FOREACH_ARRAY(tmpfs, c->temporary_filesystems, c->n_temporary_filesystems)
1270 fprintf(f, "%sTemporaryFileSystem: %s%s%s\n", prefix,
1271 tmpfs->path,
1272 isempty(tmpfs->options) ? "" : ":",
1273 strempty(tmpfs->options));
1274
1275 if (c->utmp_id)
1276 fprintf(f,
1277 "%sUtmpIdentifier: %s\n",
1278 prefix, c->utmp_id);
1279
1280 if (c->selinux_context)
1281 fprintf(f,
1282 "%sSELinuxContext: %s%s\n",
1283 prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context);
1284
1285 if (c->apparmor_profile)
1286 fprintf(f,
1287 "%sAppArmorProfile: %s%s\n",
1288 prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile);
1289
1290 if (c->smack_process_label)
1291 fprintf(f,
1292 "%sSmackProcessLabel: %s%s\n",
1293 prefix, c->smack_process_label_ignore ? "-" : "", c->smack_process_label);
1294
1295 if (c->personality != PERSONALITY_INVALID)
1296 fprintf(f,
1297 "%sPersonality: %s\n",
1298 prefix, strna(personality_to_string(c->personality)));
1299
1300 fprintf(f,
1301 "%sLockPersonality: %s\n",
1302 prefix, yes_no(c->lock_personality));
1303
1304 if (c->syscall_filter) {
1305 fprintf(f,
1306 "%sSystemCallFilter: ",
1307 prefix);
1308
1309 if (!c->syscall_allow_list)
1310 fputc('~', f);
1311
1312 #if HAVE_SECCOMP
1313 void *id, *val;
1314 bool first = true;
1315 HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
1316 _cleanup_free_ char *name = NULL;
1317 const char *errno_name = NULL;
1318 int num = PTR_TO_INT(val);
1319
1320 if (first)
1321 first = false;
1322 else
1323 fputc(' ', f);
1324
1325 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
1326 fputs(strna(name), f);
1327
1328 if (num >= 0) {
1329 errno_name = seccomp_errno_or_action_to_string(num);
1330 if (errno_name)
1331 fprintf(f, ":%s", errno_name);
1332 else
1333 fprintf(f, ":%d", num);
1334 }
1335 }
1336 #endif
1337
1338 fputc('\n', f);
1339 }
1340
1341 if (c->syscall_archs) {
1342 fprintf(f,
1343 "%sSystemCallArchitectures:",
1344 prefix);
1345
1346 #if HAVE_SECCOMP
1347 void *id;
1348 SET_FOREACH(id, c->syscall_archs)
1349 fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1)));
1350 #endif
1351 fputc('\n', f);
1352 }
1353
1354 if (exec_context_restrict_namespaces_set(c)) {
1355 _cleanup_free_ char *s = NULL;
1356
1357 r = namespace_flags_to_string(c->restrict_namespaces, &s);
1358 if (r >= 0)
1359 fprintf(f, "%sRestrictNamespaces: %s\n",
1360 prefix, strna(s));
1361 }
1362
1363 #if HAVE_LIBBPF
1364 if (exec_context_restrict_filesystems_set(c)) {
1365 char *fs;
1366 SET_FOREACH(fs, c->restrict_filesystems)
1367 fprintf(f, "%sRestrictFileSystems: %s\n", prefix, fs);
1368 }
1369 #endif
1370
1371 if (c->network_namespace_path)
1372 fprintf(f,
1373 "%sNetworkNamespacePath: %s\n",
1374 prefix, c->network_namespace_path);
1375
1376 if (c->syscall_errno > 0) {
1377 fprintf(f, "%sSystemCallErrorNumber: ", prefix);
1378
1379 #if HAVE_SECCOMP
1380 const char *errno_name = seccomp_errno_or_action_to_string(c->syscall_errno);
1381 if (errno_name)
1382 fputs(errno_name, f);
1383 else
1384 fprintf(f, "%d", c->syscall_errno);
1385 #endif
1386 fputc('\n', f);
1387 }
1388
1389 FOREACH_ARRAY(mount, c->mount_images, c->n_mount_images) {
1390 fprintf(f, "%sMountImages: %s%s:%s", prefix,
1391 mount->ignore_enoent ? "-": "",
1392 mount->source,
1393 mount->destination);
1394 LIST_FOREACH(mount_options, o, mount->mount_options)
1395 fprintf(f, ":%s:%s",
1396 partition_designator_to_string(o->partition_designator),
1397 strempty(o->options));
1398 fprintf(f, "\n");
1399 }
1400
1401 FOREACH_ARRAY(mount, c->extension_images, c->n_extension_images) {
1402 fprintf(f, "%sExtensionImages: %s%s", prefix,
1403 mount->ignore_enoent ? "-": "",
1404 mount->source);
1405 LIST_FOREACH(mount_options, o, mount->mount_options)
1406 fprintf(f, ":%s:%s",
1407 partition_designator_to_string(o->partition_designator),
1408 strempty(o->options));
1409 fprintf(f, "\n");
1410 }
1411
1412 strv_dump(f, prefix, "ExtensionDirectories", c->extension_directories);
1413 }
1414
1415 bool exec_context_maintains_privileges(const ExecContext *c) {
1416 assert(c);
1417
1418 /* Returns true if the process forked off would run under
1419 * an unchanged UID or as root. */
1420
1421 if (!c->user)
1422 return true;
1423
1424 if (STR_IN_SET(c->user, "root", "0"))
1425 return true;
1426
1427 return false;
1428 }
1429
1430 int exec_context_get_effective_ioprio(const ExecContext *c) {
1431 int p;
1432
1433 assert(c);
1434
1435 if (c->ioprio_set)
1436 return c->ioprio;
1437
1438 p = ioprio_get(IOPRIO_WHO_PROCESS, 0);
1439 if (p < 0)
1440 return IOPRIO_DEFAULT_CLASS_AND_PRIO;
1441
1442 return ioprio_normalize(p);
1443 }
1444
1445 bool exec_context_get_effective_mount_apivfs(const ExecContext *c) {
1446 assert(c);
1447
1448 /* Explicit setting wins */
1449 if (c->mount_apivfs >= 0)
1450 return c->mount_apivfs > 0;
1451
1452 /* Default to "yes" if root directory or image are specified */
1453 if (exec_context_with_rootfs(c))
1454 return true;
1455
1456 return false;
1457 }
1458
1459 void exec_context_free_log_extra_fields(ExecContext *c) {
1460 assert(c);
1461
1462 FOREACH_ARRAY(field, c->log_extra_fields, c->n_log_extra_fields)
1463 free(field->iov_base);
1464
1465 c->log_extra_fields = mfree(c->log_extra_fields);
1466 c->n_log_extra_fields = 0;
1467 }
1468
1469 void exec_context_revert_tty(ExecContext *c) {
1470 _cleanup_close_ int fd = -EBADF;
1471 const char *path;
1472 struct stat st;
1473 int r;
1474
1475 assert(c);
1476
1477 /* First, reset the TTY (possibly kicking everybody else from the TTY) */
1478 exec_context_tty_reset(c, /* parameters= */ NULL);
1479
1480 /* And then undo what chown_terminal() did earlier. Note that we only do this if we have a path
1481 * configured. If the TTY was passed to us as file descriptor we assume the TTY is opened and managed
1482 * by whoever passed it to us and thus knows better when and how to chmod()/chown() it back. */
1483 if (!exec_context_may_touch_tty(c))
1484 return;
1485
1486 path = exec_context_tty_path(c);
1487 if (!path)
1488 return;
1489
1490 fd = open(path, O_PATH|O_CLOEXEC); /* Pin the inode */
1491 if (fd < 0)
1492 return (void) log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
1493 "Failed to open TTY inode of '%s' to adjust ownership/access mode, ignoring: %m",
1494 path);
1495
1496 if (fstat(fd, &st) < 0)
1497 return (void) log_warning_errno(errno, "Failed to stat TTY '%s', ignoring: %m", path);
1498
1499 /* Let's add a superficial check that we only do this for stuff that looks like a TTY. We only check
1500 * if things are a character device, since a proper check either means we'd have to open the TTY and
1501 * use isatty(), but we'd rather not do that since opening TTYs comes with all kinds of side-effects
1502 * and is slow. Or we'd have to hardcode dev_t major information, which we'd rather avoid. Why bother
1503 * with this at all? → https://github.com/systemd/systemd/issues/19213 */
1504 if (!S_ISCHR(st.st_mode))
1505 return log_warning("Configured TTY '%s' is not actually a character device, ignoring.", path);
1506
1507 r = fchmod_and_chown(fd, TTY_MODE, 0, TTY_GID);
1508 if (r < 0)
1509 log_warning_errno(r, "Failed to reset TTY ownership/access mode of %s to " UID_FMT ":" GID_FMT ", ignoring: %m", path, (uid_t) 0, (gid_t) TTY_GID);
1510 }
1511
1512 int exec_context_get_clean_directories(
1513 ExecContext *c,
1514 char **prefix,
1515 ExecCleanMask mask,
1516 char ***ret) {
1517
1518 _cleanup_strv_free_ char **l = NULL;
1519 int r;
1520
1521 assert(c);
1522 assert(prefix);
1523 assert(ret);
1524
1525 for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
1526 if (!FLAGS_SET(mask, 1U << t))
1527 continue;
1528
1529 if (!prefix[t])
1530 continue;
1531
1532 FOREACH_ARRAY(i, c->directories[t].items, c->directories[t].n_items) {
1533 char *j;
1534
1535 j = path_join(prefix[t], i->path);
1536 if (!j)
1537 return -ENOMEM;
1538
1539 r = strv_consume(&l, j);
1540 if (r < 0)
1541 return r;
1542
1543 /* Also remove private directories unconditionally. */
1544 if (t != EXEC_DIRECTORY_CONFIGURATION) {
1545 j = path_join(prefix[t], "private", i->path);
1546 if (!j)
1547 return -ENOMEM;
1548
1549 r = strv_consume(&l, j);
1550 if (r < 0)
1551 return r;
1552 }
1553
1554 STRV_FOREACH(symlink, i->symlinks) {
1555 j = path_join(prefix[t], *symlink);
1556 if (!j)
1557 return -ENOMEM;
1558
1559 r = strv_consume(&l, j);
1560 if (r < 0)
1561 return r;
1562 }
1563 }
1564 }
1565
1566 *ret = TAKE_PTR(l);
1567 return 0;
1568 }
1569
1570 int exec_context_get_clean_mask(ExecContext *c, ExecCleanMask *ret) {
1571 ExecCleanMask mask = 0;
1572
1573 assert(c);
1574 assert(ret);
1575
1576 for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++)
1577 if (c->directories[t].n_items > 0)
1578 mask |= 1U << t;
1579
1580 *ret = mask;
1581 return 0;
1582 }
1583
1584 int exec_context_get_oom_score_adjust(const ExecContext *c) {
1585 int n = 0, r;
1586
1587 assert(c);
1588
1589 if (c->oom_score_adjust_set)
1590 return c->oom_score_adjust;
1591
1592 r = get_oom_score_adjust(&n);
1593 if (r < 0)
1594 log_debug_errno(r, "Failed to read /proc/self/oom_score_adj, ignoring: %m");
1595
1596 return n;
1597 }
1598
1599 uint64_t exec_context_get_coredump_filter(const ExecContext *c) {
1600 _cleanup_free_ char *t = NULL;
1601 uint64_t n = COREDUMP_FILTER_MASK_DEFAULT;
1602 int r;
1603
1604 assert(c);
1605
1606 if (c->coredump_filter_set)
1607 return c->coredump_filter;
1608
1609 r = read_one_line_file("/proc/self/coredump_filter", &t);
1610 if (r < 0)
1611 log_debug_errno(r, "Failed to read /proc/self/coredump_filter, ignoring: %m");
1612 else {
1613 r = safe_atoux64(t, &n);
1614 if (r < 0)
1615 log_debug_errno(r, "Failed to parse \"%s\" from /proc/self/coredump_filter, ignoring: %m", t);
1616 }
1617
1618 return n;
1619 }
1620
1621 int exec_context_get_nice(const ExecContext *c) {
1622 int n;
1623
1624 assert(c);
1625
1626 if (c->nice_set)
1627 return c->nice;
1628
1629 errno = 0;
1630 n = getpriority(PRIO_PROCESS, 0);
1631 if (errno > 0) {
1632 log_debug_errno(errno, "Failed to get process nice value, ignoring: %m");
1633 n = 0;
1634 }
1635
1636 return n;
1637 }
1638
1639 int exec_context_get_cpu_sched_policy(const ExecContext *c) {
1640 int n;
1641
1642 assert(c);
1643
1644 if (c->cpu_sched_set)
1645 return c->cpu_sched_policy;
1646
1647 n = sched_getscheduler(0);
1648 if (n < 0)
1649 log_debug_errno(errno, "Failed to get scheduler policy, ignoring: %m");
1650
1651 return n < 0 ? SCHED_OTHER : n;
1652 }
1653
1654 int exec_context_get_cpu_sched_priority(const ExecContext *c) {
1655 struct sched_param p = {};
1656 int r;
1657
1658 assert(c);
1659
1660 if (c->cpu_sched_set)
1661 return c->cpu_sched_priority;
1662
1663 r = sched_getparam(0, &p);
1664 if (r < 0)
1665 log_debug_errno(errno, "Failed to get scheduler priority, ignoring: %m");
1666
1667 return r >= 0 ? p.sched_priority : 0;
1668 }
1669
1670 uint64_t exec_context_get_timer_slack_nsec(const ExecContext *c) {
1671 int r;
1672
1673 assert(c);
1674
1675 if (c->timer_slack_nsec != NSEC_INFINITY)
1676 return c->timer_slack_nsec;
1677
1678 r = prctl(PR_GET_TIMERSLACK);
1679 if (r < 0)
1680 log_debug_errno(r, "Failed to get timer slack, ignoring: %m");
1681
1682 return (uint64_t) MAX(r, 0);
1683 }
1684
1685 bool exec_context_get_set_login_environment(const ExecContext *c) {
1686 assert(c);
1687
1688 if (c->set_login_environment >= 0)
1689 return c->set_login_environment;
1690
1691 return c->user || c->dynamic_user || c->pam_name;
1692 }
1693
1694 char** exec_context_get_syscall_filter(const ExecContext *c) {
1695 _cleanup_strv_free_ char **l = NULL;
1696
1697 assert(c);
1698
1699 #if HAVE_SECCOMP
1700 void *id, *val;
1701 HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
1702 _cleanup_free_ char *name = NULL;
1703 const char *e = NULL;
1704 char *s;
1705 int num = PTR_TO_INT(val);
1706
1707 if (c->syscall_allow_list && num >= 0)
1708 /* syscall with num >= 0 in allow-list is denied. */
1709 continue;
1710
1711 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
1712 if (!name)
1713 continue;
1714
1715 if (num >= 0) {
1716 e = seccomp_errno_or_action_to_string(num);
1717 if (e) {
1718 s = strjoin(name, ":", e);
1719 if (!s)
1720 return NULL;
1721 } else {
1722 if (asprintf(&s, "%s:%d", name, num) < 0)
1723 return NULL;
1724 }
1725 } else
1726 s = TAKE_PTR(name);
1727
1728 if (strv_consume(&l, s) < 0)
1729 return NULL;
1730 }
1731
1732 strv_sort(l);
1733 #endif
1734
1735 return l ? TAKE_PTR(l) : strv_new(NULL);
1736 }
1737
1738 char** exec_context_get_syscall_archs(const ExecContext *c) {
1739 _cleanup_strv_free_ char **l = NULL;
1740
1741 assert(c);
1742
1743 #if HAVE_SECCOMP
1744 void *id;
1745 SET_FOREACH(id, c->syscall_archs) {
1746 const char *name;
1747
1748 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
1749 if (!name)
1750 continue;
1751
1752 if (strv_extend(&l, name) < 0)
1753 return NULL;
1754 }
1755
1756 strv_sort(l);
1757 #endif
1758
1759 return l ? TAKE_PTR(l) : strv_new(NULL);
1760 }
1761
1762 char** exec_context_get_syscall_log(const ExecContext *c) {
1763 _cleanup_strv_free_ char **l = NULL;
1764
1765 assert(c);
1766
1767 #if HAVE_SECCOMP
1768 void *id, *val;
1769 HASHMAP_FOREACH_KEY(val, id, c->syscall_log) {
1770 char *name = NULL;
1771
1772 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
1773 if (!name)
1774 continue;
1775
1776 if (strv_consume(&l, name) < 0)
1777 return NULL;
1778 }
1779
1780 strv_sort(l);
1781 #endif
1782
1783 return l ? TAKE_PTR(l) : strv_new(NULL);
1784 }
1785
1786 char** exec_context_get_address_families(const ExecContext *c) {
1787 _cleanup_strv_free_ char **l = NULL;
1788 void *af;
1789
1790 assert(c);
1791
1792 SET_FOREACH(af, c->address_families) {
1793 const char *name;
1794
1795 name = af_to_name(PTR_TO_INT(af));
1796 if (!name)
1797 continue;
1798
1799 if (strv_extend(&l, name) < 0)
1800 return NULL;
1801 }
1802
1803 strv_sort(l);
1804
1805 return l ? TAKE_PTR(l) : strv_new(NULL);
1806 }
1807
1808 char** exec_context_get_restrict_filesystems(const ExecContext *c) {
1809 _cleanup_strv_free_ char **l = NULL;
1810
1811 assert(c);
1812
1813 #if HAVE_LIBBPF
1814 l = set_get_strv(c->restrict_filesystems);
1815 if (!l)
1816 return NULL;
1817
1818 strv_sort(l);
1819 #endif
1820
1821 return l ? TAKE_PTR(l) : strv_new(NULL);
1822 }
1823
1824 void exec_status_start(ExecStatus *s, pid_t pid, const dual_timestamp *ts) {
1825 assert(s);
1826
1827 *s = (ExecStatus) {
1828 .pid = pid,
1829 };
1830
1831 if (ts)
1832 s->start_timestamp = *ts;
1833 else
1834 dual_timestamp_now(&s->start_timestamp);
1835 }
1836
1837 void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status) {
1838 assert(s);
1839
1840 if (s->pid != pid)
1841 *s = (ExecStatus) {
1842 .pid = pid,
1843 };
1844
1845 dual_timestamp_now(&s->exit_timestamp);
1846
1847 s->code = code;
1848 s->status = status;
1849
1850 if (context && context->utmp_id)
1851 (void) utmp_put_dead_process(context->utmp_id, pid, code, status);
1852 }
1853
1854 void exec_status_handoff(ExecStatus *s, const struct ucred *ucred, const dual_timestamp *ts) {
1855 assert(s);
1856 assert(ucred);
1857 assert(ts);
1858
1859 if (ucred->pid != s->pid)
1860 *s = (ExecStatus) {
1861 .pid = ucred->pid,
1862 };
1863
1864 s->handoff_timestamp = *ts;
1865 }
1866
1867 void exec_status_reset(ExecStatus *s) {
1868 assert(s);
1869
1870 *s = (ExecStatus) {};
1871 }
1872
1873 void exec_status_dump(const ExecStatus *s, FILE *f, const char *prefix) {
1874 assert(s);
1875 assert(f);
1876
1877 if (s->pid <= 0)
1878 return;
1879
1880 prefix = strempty(prefix);
1881
1882 fprintf(f,
1883 "%sPID: "PID_FMT"\n",
1884 prefix, s->pid);
1885
1886 if (dual_timestamp_is_set(&s->start_timestamp))
1887 fprintf(f,
1888 "%sStart Timestamp: %s\n",
1889 prefix, FORMAT_TIMESTAMP_STYLE(s->start_timestamp.realtime, TIMESTAMP_US));
1890
1891 if (dual_timestamp_is_set(&s->handoff_timestamp) && dual_timestamp_is_set(&s->start_timestamp) &&
1892 s->handoff_timestamp.monotonic > s->start_timestamp.monotonic)
1893 fprintf(f,
1894 "%sHandoff Timestamp: %s since start\n",
1895 prefix,
1896 FORMAT_TIMESPAN(usec_sub_unsigned(s->handoff_timestamp.monotonic, s->start_timestamp.monotonic), 1));
1897 else
1898 fprintf(f,
1899 "%sHandoff Timestamp: %s\n",
1900 prefix, FORMAT_TIMESTAMP_STYLE(s->handoff_timestamp.realtime, TIMESTAMP_US));
1901
1902 if (dual_timestamp_is_set(&s->exit_timestamp)) {
1903
1904 if (dual_timestamp_is_set(&s->handoff_timestamp) && s->exit_timestamp.monotonic > s->handoff_timestamp.monotonic)
1905 fprintf(f,
1906 "%sExit Timestamp: %s since handoff\n",
1907 prefix,
1908 FORMAT_TIMESPAN(usec_sub_unsigned(s->exit_timestamp.monotonic, s->handoff_timestamp.monotonic), 1));
1909 else if (dual_timestamp_is_set(&s->start_timestamp) && s->exit_timestamp.monotonic > s->start_timestamp.monotonic)
1910 fprintf(f,
1911 "%sExit Timestamp: %s since start\n",
1912 prefix,
1913 FORMAT_TIMESPAN(usec_sub_unsigned(s->exit_timestamp.monotonic, s->start_timestamp.monotonic), 1));
1914 else
1915 fprintf(f,
1916 "%sExit Timestamp: %s\n",
1917 prefix, FORMAT_TIMESTAMP_STYLE(s->exit_timestamp.realtime, TIMESTAMP_US));
1918
1919 fprintf(f,
1920 "%sExit Code: %s\n"
1921 "%sExit Status: %i\n",
1922 prefix, sigchld_code_to_string(s->code),
1923 prefix, s->status);
1924 }
1925 }
1926
1927 void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
1928 _cleanup_free_ char *cmd = NULL;
1929 const char *prefix2;
1930
1931 assert(c);
1932 assert(f);
1933
1934 prefix = strempty(prefix);
1935 prefix2 = strjoina(prefix, "\t");
1936
1937 cmd = quote_command_line(c->argv, SHELL_ESCAPE_EMPTY);
1938
1939 fprintf(f,
1940 "%sCommand Line: %s\n",
1941 prefix, strnull(cmd));
1942
1943 exec_status_dump(&c->exec_status, f, prefix2);
1944 }
1945
1946 void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
1947 assert(f);
1948
1949 prefix = strempty(prefix);
1950
1951 LIST_FOREACH(command, i, c)
1952 exec_command_dump(i, f, prefix);
1953 }
1954
1955 void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
1956 ExecCommand *end;
1957
1958 assert(l);
1959 assert(e);
1960
1961 if (*l) {
1962 /* It's kind of important, that we keep the order here */
1963 end = LIST_FIND_TAIL(command, *l);
1964 LIST_INSERT_AFTER(command, *l, end, e);
1965 } else
1966 *l = e;
1967 }
1968
1969 int exec_command_set(ExecCommand *c, const char *path, ...) {
1970 va_list ap;
1971 char **l, *p;
1972
1973 assert(c);
1974 assert(path);
1975
1976 va_start(ap, path);
1977 l = strv_new_ap(path, ap);
1978 va_end(ap);
1979
1980 if (!l)
1981 return -ENOMEM;
1982
1983 p = strdup(path);
1984 if (!p) {
1985 strv_free(l);
1986 return -ENOMEM;
1987 }
1988
1989 free_and_replace(c->path, p);
1990
1991 return strv_free_and_replace(c->argv, l);
1992 }
1993
1994 int exec_command_append(ExecCommand *c, const char *path, ...) {
1995 _cleanup_strv_free_ char **l = NULL;
1996 va_list ap;
1997 int r;
1998
1999 assert(c);
2000 assert(path);
2001
2002 va_start(ap, path);
2003 l = strv_new_ap(path, ap);
2004 va_end(ap);
2005
2006 if (!l)
2007 return -ENOMEM;
2008
2009 r = strv_extend_strv(&c->argv, l, false);
2010 if (r < 0)
2011 return r;
2012
2013 return 0;
2014 }
2015
2016 static char *destroy_tree(char *path) {
2017 if (!path)
2018 return NULL;
2019
2020 if (!path_equal(path, RUN_SYSTEMD_EMPTY)) {
2021 log_debug("Spawning process to nuke '%s'", path);
2022
2023 (void) asynchronous_rm_rf(path, REMOVE_ROOT|REMOVE_SUBVOLUME|REMOVE_PHYSICAL);
2024 }
2025
2026 return mfree(path);
2027 }
2028
2029 void exec_shared_runtime_done(ExecSharedRuntime *rt) {
2030 assert(rt);
2031
2032 if (rt->manager)
2033 (void) hashmap_remove(rt->manager->exec_shared_runtime_by_id, rt->id);
2034
2035 rt->id = mfree(rt->id);
2036 rt->tmp_dir = mfree(rt->tmp_dir);
2037 rt->var_tmp_dir = mfree(rt->var_tmp_dir);
2038 safe_close_pair(rt->netns_storage_socket);
2039 safe_close_pair(rt->ipcns_storage_socket);
2040 }
2041
2042 static ExecSharedRuntime* exec_shared_runtime_free(ExecSharedRuntime *rt) {
2043 if (!rt)
2044 return NULL;
2045
2046 exec_shared_runtime_done(rt);
2047 return mfree(rt);
2048 }
2049
2050 DEFINE_TRIVIAL_UNREF_FUNC(ExecSharedRuntime, exec_shared_runtime, exec_shared_runtime_free);
2051 DEFINE_TRIVIAL_CLEANUP_FUNC(ExecSharedRuntime*, exec_shared_runtime_free);
2052
2053 ExecSharedRuntime* exec_shared_runtime_destroy(ExecSharedRuntime *rt) {
2054 if (!rt)
2055 return NULL;
2056
2057 assert(rt->n_ref > 0);
2058 rt->n_ref--;
2059
2060 if (rt->n_ref > 0)
2061 return NULL;
2062
2063 rt->tmp_dir = destroy_tree(rt->tmp_dir);
2064 rt->var_tmp_dir = destroy_tree(rt->var_tmp_dir);
2065
2066 return exec_shared_runtime_free(rt);
2067 }
2068
2069 static int exec_shared_runtime_allocate(ExecSharedRuntime **ret, const char *id) {
2070 _cleanup_free_ char *id_copy = NULL;
2071 ExecSharedRuntime *n;
2072
2073 assert(ret);
2074
2075 id_copy = strdup(id);
2076 if (!id_copy)
2077 return -ENOMEM;
2078
2079 n = new(ExecSharedRuntime, 1);
2080 if (!n)
2081 return -ENOMEM;
2082
2083 *n = (ExecSharedRuntime) {
2084 .id = TAKE_PTR(id_copy),
2085 .netns_storage_socket = EBADF_PAIR,
2086 .ipcns_storage_socket = EBADF_PAIR,
2087 };
2088
2089 *ret = n;
2090 return 0;
2091 }
2092
2093 static int exec_shared_runtime_add(
2094 Manager *m,
2095 const char *id,
2096 char **tmp_dir,
2097 char **var_tmp_dir,
2098 int netns_storage_socket[2],
2099 int ipcns_storage_socket[2],
2100 ExecSharedRuntime **ret) {
2101
2102 _cleanup_(exec_shared_runtime_freep) ExecSharedRuntime *rt = NULL;
2103 int r;
2104
2105 assert(m);
2106 assert(id);
2107
2108 /* tmp_dir, var_tmp_dir, {net,ipc}ns_storage_socket fds are donated on success */
2109
2110 r = exec_shared_runtime_allocate(&rt, id);
2111 if (r < 0)
2112 return r;
2113
2114 r = hashmap_ensure_put(&m->exec_shared_runtime_by_id, &string_hash_ops, rt->id, rt);
2115 if (r < 0)
2116 return r;
2117
2118 assert(!!rt->tmp_dir == !!rt->var_tmp_dir); /* We require both to be set together */
2119 rt->tmp_dir = TAKE_PTR(*tmp_dir);
2120 rt->var_tmp_dir = TAKE_PTR(*var_tmp_dir);
2121
2122 if (netns_storage_socket) {
2123 rt->netns_storage_socket[0] = TAKE_FD(netns_storage_socket[0]);
2124 rt->netns_storage_socket[1] = TAKE_FD(netns_storage_socket[1]);
2125 }
2126
2127 if (ipcns_storage_socket) {
2128 rt->ipcns_storage_socket[0] = TAKE_FD(ipcns_storage_socket[0]);
2129 rt->ipcns_storage_socket[1] = TAKE_FD(ipcns_storage_socket[1]);
2130 }
2131
2132 rt->manager = m;
2133
2134 if (ret)
2135 *ret = rt;
2136 /* do not remove created ExecSharedRuntime object when the operation succeeds. */
2137 TAKE_PTR(rt);
2138 return 0;
2139 }
2140
2141 static int exec_shared_runtime_make(
2142 Manager *m,
2143 const ExecContext *c,
2144 const char *id,
2145 ExecSharedRuntime **ret) {
2146
2147 _cleanup_(namespace_cleanup_tmpdirp) char *tmp_dir = NULL, *var_tmp_dir = NULL;
2148 _cleanup_close_pair_ int netns_storage_socket[2] = EBADF_PAIR, ipcns_storage_socket[2] = EBADF_PAIR;
2149 int r;
2150
2151 assert(m);
2152 assert(c);
2153 assert(id);
2154
2155 /* It is not necessary to create ExecSharedRuntime object. */
2156 if (!exec_needs_network_namespace(c) && !exec_needs_ipc_namespace(c) && !c->private_tmp) {
2157 *ret = NULL;
2158 return 0;
2159 }
2160
2161 if (c->private_tmp &&
2162 !(prefixed_path_strv_contains(c->inaccessible_paths, "/tmp") &&
2163 (prefixed_path_strv_contains(c->inaccessible_paths, "/var/tmp") ||
2164 prefixed_path_strv_contains(c->inaccessible_paths, "/var")))) {
2165 r = setup_tmp_dirs(id, &tmp_dir, &var_tmp_dir);
2166 if (r < 0)
2167 return r;
2168 }
2169
2170 if (exec_needs_network_namespace(c))
2171 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, netns_storage_socket) < 0)
2172 return -errno;
2173
2174 if (exec_needs_ipc_namespace(c))
2175 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, ipcns_storage_socket) < 0)
2176 return -errno;
2177
2178 r = exec_shared_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_storage_socket, ipcns_storage_socket, ret);
2179 if (r < 0)
2180 return r;
2181
2182 return 1;
2183 }
2184
2185 int exec_shared_runtime_acquire(Manager *m, const ExecContext *c, const char *id, bool create, ExecSharedRuntime **ret) {
2186 ExecSharedRuntime *rt;
2187 int r;
2188
2189 assert(m);
2190 assert(id);
2191 assert(ret);
2192
2193 rt = hashmap_get(m->exec_shared_runtime_by_id, id);
2194 if (rt)
2195 /* We already have an ExecSharedRuntime object, let's increase the ref count and reuse it */
2196 goto ref;
2197
2198 if (!create) {
2199 *ret = NULL;
2200 return 0;
2201 }
2202
2203 /* If not found, then create a new object. */
2204 r = exec_shared_runtime_make(m, c, id, &rt);
2205 if (r < 0)
2206 return r;
2207 if (r == 0) {
2208 /* When r == 0, it is not necessary to create ExecSharedRuntime object. */
2209 *ret = NULL;
2210 return 0;
2211 }
2212
2213 ref:
2214 /* increment reference counter. */
2215 rt->n_ref++;
2216 *ret = rt;
2217 return 1;
2218 }
2219
2220 int exec_shared_runtime_serialize(const Manager *m, FILE *f, FDSet *fds) {
2221 ExecSharedRuntime *rt;
2222
2223 assert(m);
2224 assert(f);
2225 assert(fds);
2226
2227 HASHMAP_FOREACH(rt, m->exec_shared_runtime_by_id) {
2228 fprintf(f, "exec-runtime=%s", rt->id);
2229
2230 if (rt->tmp_dir)
2231 fprintf(f, " tmp-dir=%s", rt->tmp_dir);
2232
2233 if (rt->var_tmp_dir)
2234 fprintf(f, " var-tmp-dir=%s", rt->var_tmp_dir);
2235
2236 if (rt->netns_storage_socket[0] >= 0) {
2237 int copy;
2238
2239 copy = fdset_put_dup(fds, rt->netns_storage_socket[0]);
2240 if (copy < 0)
2241 return copy;
2242
2243 fprintf(f, " netns-socket-0=%i", copy);
2244 }
2245
2246 if (rt->netns_storage_socket[1] >= 0) {
2247 int copy;
2248
2249 copy = fdset_put_dup(fds, rt->netns_storage_socket[1]);
2250 if (copy < 0)
2251 return copy;
2252
2253 fprintf(f, " netns-socket-1=%i", copy);
2254 }
2255
2256 if (rt->ipcns_storage_socket[0] >= 0) {
2257 int copy;
2258
2259 copy = fdset_put_dup(fds, rt->ipcns_storage_socket[0]);
2260 if (copy < 0)
2261 return copy;
2262
2263 fprintf(f, " ipcns-socket-0=%i", copy);
2264 }
2265
2266 if (rt->ipcns_storage_socket[1] >= 0) {
2267 int copy;
2268
2269 copy = fdset_put_dup(fds, rt->ipcns_storage_socket[1]);
2270 if (copy < 0)
2271 return copy;
2272
2273 fprintf(f, " ipcns-socket-1=%i", copy);
2274 }
2275
2276 fputc('\n', f);
2277 }
2278
2279 return 0;
2280 }
2281
2282 int exec_shared_runtime_deserialize_compat(Unit *u, const char *key, const char *value, FDSet *fds) {
2283 _cleanup_(exec_shared_runtime_freep) ExecSharedRuntime *rt_create = NULL;
2284 ExecSharedRuntime *rt = NULL;
2285 int r;
2286
2287 /* This is for the migration from old (v237 or earlier) deserialization text.
2288 * Due to the bug #7790, this may not work with the units that use JoinsNamespaceOf=.
2289 * Even if the ExecSharedRuntime object originally created by the other unit, we cannot judge
2290 * so or not from the serialized text, then we always creates a new object owned by this. */
2291
2292 assert(u);
2293 assert(key);
2294 assert(value);
2295
2296 /* Manager manages ExecSharedRuntime objects by the unit id.
2297 * So, we omit the serialized text when the unit does not have id (yet?)... */
2298 if (isempty(u->id)) {
2299 log_unit_debug(u, "Invocation ID not found. Dropping runtime parameter.");
2300 return 0;
2301 }
2302
2303 if (u->manager) {
2304 if (hashmap_ensure_allocated(&u->manager->exec_shared_runtime_by_id, &string_hash_ops) < 0)
2305 return log_oom();
2306
2307 rt = hashmap_get(u->manager->exec_shared_runtime_by_id, u->id);
2308 }
2309 if (!rt) {
2310 if (exec_shared_runtime_allocate(&rt_create, u->id) < 0)
2311 return log_oom();
2312
2313 rt = rt_create;
2314 }
2315
2316 if (streq(key, "tmp-dir")) {
2317 if (free_and_strdup_warn(&rt->tmp_dir, value) < 0)
2318 return -ENOMEM;
2319
2320 } else if (streq(key, "var-tmp-dir")) {
2321 if (free_and_strdup_warn(&rt->var_tmp_dir, value) < 0)
2322 return -ENOMEM;
2323
2324 } else if (streq(key, "netns-socket-0")) {
2325
2326 safe_close(rt->netns_storage_socket[0]);
2327 rt->netns_storage_socket[0] = deserialize_fd(fds, value);
2328 if (rt->netns_storage_socket[0] < 0)
2329 return 0;
2330
2331 } else if (streq(key, "netns-socket-1")) {
2332
2333 safe_close(rt->netns_storage_socket[1]);
2334 rt->netns_storage_socket[1] = deserialize_fd(fds, value);
2335 if (rt->netns_storage_socket[1] < 0)
2336 return 0;
2337 } else
2338 return 0;
2339
2340 /* If the object is newly created, then put it to the hashmap which manages ExecSharedRuntime objects. */
2341 if (rt_create && u->manager) {
2342 r = hashmap_put(u->manager->exec_shared_runtime_by_id, rt_create->id, rt_create);
2343 if (r < 0) {
2344 log_unit_debug_errno(u, r, "Failed to put runtime parameter to manager's storage: %m");
2345 return 0;
2346 }
2347
2348 rt_create->manager = u->manager;
2349
2350 /* Avoid cleanup */
2351 TAKE_PTR(rt_create);
2352 }
2353
2354 return 1;
2355 }
2356
2357 int exec_shared_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
2358 _cleanup_free_ char *tmp_dir = NULL, *var_tmp_dir = NULL;
2359 char *id = NULL;
2360 int r, netns_fdpair[] = {-1, -1}, ipcns_fdpair[] = {-1, -1};
2361 const char *p, *v = ASSERT_PTR(value);
2362 size_t n;
2363
2364 assert(m);
2365 assert(fds);
2366
2367 n = strcspn(v, " ");
2368 id = strndupa_safe(v, n);
2369 if (v[n] != ' ')
2370 goto finalize;
2371 p = v + n + 1;
2372
2373 v = startswith(p, "tmp-dir=");
2374 if (v) {
2375 n = strcspn(v, " ");
2376 tmp_dir = strndup(v, n);
2377 if (!tmp_dir)
2378 return log_oom();
2379 if (v[n] != ' ')
2380 goto finalize;
2381 p = v + n + 1;
2382 }
2383
2384 v = startswith(p, "var-tmp-dir=");
2385 if (v) {
2386 n = strcspn(v, " ");
2387 var_tmp_dir = strndup(v, n);
2388 if (!var_tmp_dir)
2389 return log_oom();
2390 if (v[n] != ' ')
2391 goto finalize;
2392 p = v + n + 1;
2393 }
2394
2395 v = startswith(p, "netns-socket-0=");
2396 if (v) {
2397 char *buf;
2398
2399 n = strcspn(v, " ");
2400 buf = strndupa_safe(v, n);
2401
2402 netns_fdpair[0] = deserialize_fd(fds, buf);
2403 if (netns_fdpair[0] < 0)
2404 return netns_fdpair[0];
2405 if (v[n] != ' ')
2406 goto finalize;
2407 p = v + n + 1;
2408 }
2409
2410 v = startswith(p, "netns-socket-1=");
2411 if (v) {
2412 char *buf;
2413
2414 n = strcspn(v, " ");
2415 buf = strndupa_safe(v, n);
2416
2417 netns_fdpair[1] = deserialize_fd(fds, buf);
2418 if (netns_fdpair[1] < 0)
2419 return netns_fdpair[1];
2420 if (v[n] != ' ')
2421 goto finalize;
2422 p = v + n + 1;
2423 }
2424
2425 v = startswith(p, "ipcns-socket-0=");
2426 if (v) {
2427 char *buf;
2428
2429 n = strcspn(v, " ");
2430 buf = strndupa_safe(v, n);
2431
2432 ipcns_fdpair[0] = deserialize_fd(fds, buf);
2433 if (ipcns_fdpair[0] < 0)
2434 return ipcns_fdpair[0];
2435 if (v[n] != ' ')
2436 goto finalize;
2437 p = v + n + 1;
2438 }
2439
2440 v = startswith(p, "ipcns-socket-1=");
2441 if (v) {
2442 char *buf;
2443
2444 n = strcspn(v, " ");
2445 buf = strndupa_safe(v, n);
2446
2447 ipcns_fdpair[1] = deserialize_fd(fds, buf);
2448 if (ipcns_fdpair[1] < 0)
2449 return ipcns_fdpair[1];
2450 }
2451
2452 finalize:
2453 r = exec_shared_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_fdpair, ipcns_fdpair, NULL);
2454 if (r < 0)
2455 return log_debug_errno(r, "Failed to add exec-runtime: %m");
2456 return 0;
2457 }
2458
2459 void exec_shared_runtime_vacuum(Manager *m) {
2460 ExecSharedRuntime *rt;
2461
2462 assert(m);
2463
2464 /* Free unreferenced ExecSharedRuntime objects. This is used after manager deserialization process. */
2465
2466 HASHMAP_FOREACH(rt, m->exec_shared_runtime_by_id) {
2467 if (rt->n_ref > 0)
2468 continue;
2469
2470 (void) exec_shared_runtime_free(rt);
2471 }
2472 }
2473
2474 int exec_runtime_make(
2475 const Unit *unit,
2476 const ExecContext *context,
2477 ExecSharedRuntime *shared,
2478 DynamicCreds *creds,
2479 ExecRuntime **ret) {
2480 _cleanup_close_pair_ int ephemeral_storage_socket[2] = EBADF_PAIR;
2481 _cleanup_free_ char *ephemeral = NULL;
2482 _cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL;
2483 int r;
2484
2485 assert(unit);
2486 assert(context);
2487 assert(ret);
2488
2489 if (!shared && !creds && !exec_needs_ephemeral(context)) {
2490 *ret = NULL;
2491 return 0;
2492 }
2493
2494 if (exec_needs_ephemeral(context)) {
2495 r = mkdir_p("/var/lib/systemd/ephemeral-trees", 0755);
2496 if (r < 0)
2497 return r;
2498
2499 r = tempfn_random_child("/var/lib/systemd/ephemeral-trees", unit->id, &ephemeral);
2500 if (r < 0)
2501 return r;
2502
2503 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, ephemeral_storage_socket) < 0)
2504 return -errno;
2505 }
2506
2507 rt = new(ExecRuntime, 1);
2508 if (!rt)
2509 return -ENOMEM;
2510
2511 *rt = (ExecRuntime) {
2512 .shared = shared,
2513 .dynamic_creds = creds,
2514 .ephemeral_copy = TAKE_PTR(ephemeral),
2515 .ephemeral_storage_socket[0] = TAKE_FD(ephemeral_storage_socket[0]),
2516 .ephemeral_storage_socket[1] = TAKE_FD(ephemeral_storage_socket[1]),
2517 };
2518
2519 *ret = TAKE_PTR(rt);
2520 return 1;
2521 }
2522
2523 ExecRuntime* exec_runtime_free(ExecRuntime *rt) {
2524 if (!rt)
2525 return NULL;
2526
2527 exec_shared_runtime_unref(rt->shared);
2528 dynamic_creds_unref(rt->dynamic_creds);
2529
2530 rt->ephemeral_copy = destroy_tree(rt->ephemeral_copy);
2531
2532 safe_close_pair(rt->ephemeral_storage_socket);
2533 return mfree(rt);
2534 }
2535
2536 ExecRuntime* exec_runtime_destroy(ExecRuntime *rt) {
2537 if (!rt)
2538 return NULL;
2539
2540 rt->shared = exec_shared_runtime_destroy(rt->shared);
2541 rt->dynamic_creds = dynamic_creds_destroy(rt->dynamic_creds);
2542 return exec_runtime_free(rt);
2543 }
2544
2545 void exec_runtime_clear(ExecRuntime *rt) {
2546 if (!rt)
2547 return;
2548
2549 safe_close_pair(rt->ephemeral_storage_socket);
2550 rt->ephemeral_copy = mfree(rt->ephemeral_copy);
2551 }
2552
2553 void exec_params_shallow_clear(ExecParameters *p) {
2554 if (!p)
2555 return;
2556
2557 /* This is called on the PID1 side, as many of the struct's FDs are only borrowed, and actually
2558 * owned by the manager or other objects, and reused across multiple units. */
2559
2560 p->environment = strv_free(p->environment);
2561 p->fd_names = strv_free(p->fd_names);
2562 p->files_env = strv_free(p->files_env);
2563 p->fds = mfree(p->fds);
2564 p->exec_fd = safe_close(p->exec_fd);
2565 p->user_lookup_fd = -EBADF;
2566 p->bpf_restrict_fs_map_fd = -EBADF;
2567 p->unit_id = mfree(p->unit_id);
2568 p->invocation_id = SD_ID128_NULL;
2569 p->invocation_id_string[0] = '\0';
2570 p->confirm_spawn = mfree(p->confirm_spawn);
2571 }
2572
2573 void exec_params_deep_clear(ExecParameters *p) {
2574 if (!p)
2575 return;
2576
2577 /* This is called on the sd-executor side, where everything received is owned by the process and has
2578 * to be fully cleaned up to make sanitizers and analyzers happy, as opposed as the shallow clean
2579 * function above. */
2580
2581 close_many_unset(p->fds, p->n_socket_fds + p->n_storage_fds);
2582
2583 p->cgroup_path = mfree(p->cgroup_path);
2584
2585 if (p->prefix) {
2586 free_many_charp(p->prefix, _EXEC_DIRECTORY_TYPE_MAX);
2587 p->prefix = mfree(p->prefix);
2588 }
2589
2590 p->received_credentials_directory = mfree(p->received_credentials_directory);
2591 p->received_encrypted_credentials_directory = mfree(p->received_encrypted_credentials_directory);
2592
2593 if (p->idle_pipe) {
2594 close_many_and_free(p->idle_pipe, 4);
2595 p->idle_pipe = NULL;
2596 }
2597
2598 p->stdin_fd = safe_close(p->stdin_fd);
2599 p->stdout_fd = safe_close(p->stdout_fd);
2600 p->stderr_fd = safe_close(p->stderr_fd);
2601
2602 p->notify_socket = mfree(p->notify_socket);
2603
2604 open_file_free_many(&p->open_files);
2605
2606 p->fallback_smack_process_label = mfree(p->fallback_smack_process_label);
2607
2608 exec_params_shallow_clear(p);
2609 }
2610
2611 void exec_directory_done(ExecDirectory *d) {
2612 if (!d)
2613 return;
2614
2615 FOREACH_ARRAY(i, d->items, d->n_items) {
2616 free(i->path);
2617 strv_free(i->symlinks);
2618 }
2619
2620 d->items = mfree(d->items);
2621 d->n_items = 0;
2622 d->mode = 0755;
2623 }
2624
2625 static ExecDirectoryItem *exec_directory_find(ExecDirectory *d, const char *path) {
2626 assert(d);
2627 assert(path);
2628
2629 FOREACH_ARRAY(i, d->items, d->n_items)
2630 if (path_equal(i->path, path))
2631 return i;
2632
2633 return NULL;
2634 }
2635
2636 int exec_directory_add(ExecDirectory *d, const char *path, const char *symlink) {
2637 _cleanup_strv_free_ char **s = NULL;
2638 _cleanup_free_ char *p = NULL;
2639 ExecDirectoryItem *existing;
2640 int r;
2641
2642 assert(d);
2643 assert(path);
2644
2645 existing = exec_directory_find(d, path);
2646 if (existing) {
2647 r = strv_extend(&existing->symlinks, symlink);
2648 if (r < 0)
2649 return r;
2650
2651 return 0; /* existing item is updated */
2652 }
2653
2654 p = strdup(path);
2655 if (!p)
2656 return -ENOMEM;
2657
2658 if (symlink) {
2659 s = strv_new(symlink);
2660 if (!s)
2661 return -ENOMEM;
2662 }
2663
2664 if (!GREEDY_REALLOC(d->items, d->n_items + 1))
2665 return -ENOMEM;
2666
2667 d->items[d->n_items++] = (ExecDirectoryItem) {
2668 .path = TAKE_PTR(p),
2669 .symlinks = TAKE_PTR(s),
2670 };
2671
2672 return 1; /* new item is added */
2673 }
2674
2675 static int exec_directory_item_compare_func(const ExecDirectoryItem *a, const ExecDirectoryItem *b) {
2676 assert(a);
2677 assert(b);
2678
2679 return path_compare(a->path, b->path);
2680 }
2681
2682 void exec_directory_sort(ExecDirectory *d) {
2683 assert(d);
2684
2685 /* Sort the exec directories to make always parent directories processed at first in
2686 * setup_exec_directory(), e.g., even if StateDirectory=foo/bar foo, we need to create foo at first,
2687 * then foo/bar. Also, set .only_create flag if one of the parent directories is contained in the
2688 * list. See also comments in setup_exec_directory() and issue #24783. */
2689
2690 if (d->n_items <= 1)
2691 return;
2692
2693 typesafe_qsort(d->items, d->n_items, exec_directory_item_compare_func);
2694
2695 for (size_t i = 1; i < d->n_items; i++)
2696 for (size_t j = 0; j < i; j++)
2697 if (path_startswith(d->items[i].path, d->items[j].path)) {
2698 d->items[i].only_create = true;
2699 break;
2700 }
2701 }
2702
2703 ExecCleanMask exec_clean_mask_from_string(const char *s) {
2704 ExecDirectoryType t;
2705
2706 assert(s);
2707
2708 if (streq(s, "all"))
2709 return EXEC_CLEAN_ALL;
2710 if (streq(s, "fdstore"))
2711 return EXEC_CLEAN_FDSTORE;
2712
2713 t = exec_resource_type_from_string(s);
2714 if (t < 0)
2715 return (ExecCleanMask) t;
2716
2717 return 1U << t;
2718 }
2719
2720 static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
2721 [EXEC_INPUT_NULL] = "null",
2722 [EXEC_INPUT_TTY] = "tty",
2723 [EXEC_INPUT_TTY_FORCE] = "tty-force",
2724 [EXEC_INPUT_TTY_FAIL] = "tty-fail",
2725 [EXEC_INPUT_SOCKET] = "socket",
2726 [EXEC_INPUT_NAMED_FD] = "fd",
2727 [EXEC_INPUT_DATA] = "data",
2728 [EXEC_INPUT_FILE] = "file",
2729 };
2730
2731 DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
2732
2733 static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
2734 [EXEC_OUTPUT_INHERIT] = "inherit",
2735 [EXEC_OUTPUT_NULL] = "null",
2736 [EXEC_OUTPUT_TTY] = "tty",
2737 [EXEC_OUTPUT_KMSG] = "kmsg",
2738 [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
2739 [EXEC_OUTPUT_JOURNAL] = "journal",
2740 [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
2741 [EXEC_OUTPUT_SOCKET] = "socket",
2742 [EXEC_OUTPUT_NAMED_FD] = "fd",
2743 [EXEC_OUTPUT_FILE] = "file",
2744 [EXEC_OUTPUT_FILE_APPEND] = "append",
2745 [EXEC_OUTPUT_FILE_TRUNCATE] = "truncate",
2746 };
2747
2748 DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
2749
2750 static const char* const exec_utmp_mode_table[_EXEC_UTMP_MODE_MAX] = {
2751 [EXEC_UTMP_INIT] = "init",
2752 [EXEC_UTMP_LOGIN] = "login",
2753 [EXEC_UTMP_USER] = "user",
2754 };
2755
2756 DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode, ExecUtmpMode);
2757
2758 static const char* const exec_preserve_mode_table[_EXEC_PRESERVE_MODE_MAX] = {
2759 [EXEC_PRESERVE_NO] = "no",
2760 [EXEC_PRESERVE_YES] = "yes",
2761 [EXEC_PRESERVE_RESTART] = "restart",
2762 };
2763
2764 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode, ExecPreserveMode, EXEC_PRESERVE_YES);
2765
2766 /* This table maps ExecDirectoryType to the setting it is configured with in the unit */
2767 static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
2768 [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
2769 [EXEC_DIRECTORY_STATE] = "StateDirectory",
2770 [EXEC_DIRECTORY_CACHE] = "CacheDirectory",
2771 [EXEC_DIRECTORY_LOGS] = "LogsDirectory",
2772 [EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
2773 };
2774
2775 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);
2776
2777 /* This table maps ExecDirectoryType to the symlink setting it is configured with in the unit */
2778 static const char* const exec_directory_type_symlink_table[_EXEC_DIRECTORY_TYPE_MAX] = {
2779 [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectorySymlink",
2780 [EXEC_DIRECTORY_STATE] = "StateDirectorySymlink",
2781 [EXEC_DIRECTORY_CACHE] = "CacheDirectorySymlink",
2782 [EXEC_DIRECTORY_LOGS] = "LogsDirectorySymlink",
2783 [EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectorySymlink",
2784 };
2785
2786 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_symlink, ExecDirectoryType);
2787
2788 static const char* const exec_directory_type_mode_table[_EXEC_DIRECTORY_TYPE_MAX] = {
2789 [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectoryMode",
2790 [EXEC_DIRECTORY_STATE] = "StateDirectoryMode",
2791 [EXEC_DIRECTORY_CACHE] = "CacheDirectoryMode",
2792 [EXEC_DIRECTORY_LOGS] = "LogsDirectoryMode",
2793 [EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectoryMode",
2794 };
2795
2796 DEFINE_STRING_TABLE_LOOKUP(exec_directory_type_mode, ExecDirectoryType);
2797
2798 /* And this table maps ExecDirectoryType too, but to a generic term identifying the type of resource. This
2799 * one is supposed to be generic enough to be used for unit types that don't use ExecContext and per-unit
2800 * directories, specifically .timer units with their timestamp touch file. */
2801 static const char* const exec_resource_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
2802 [EXEC_DIRECTORY_RUNTIME] = "runtime",
2803 [EXEC_DIRECTORY_STATE] = "state",
2804 [EXEC_DIRECTORY_CACHE] = "cache",
2805 [EXEC_DIRECTORY_LOGS] = "logs",
2806 [EXEC_DIRECTORY_CONFIGURATION] = "configuration",
2807 };
2808
2809 DEFINE_STRING_TABLE_LOOKUP(exec_resource_type, ExecDirectoryType);
2810
2811 static const char* const exec_keyring_mode_table[_EXEC_KEYRING_MODE_MAX] = {
2812 [EXEC_KEYRING_INHERIT] = "inherit",
2813 [EXEC_KEYRING_PRIVATE] = "private",
2814 [EXEC_KEYRING_SHARED] = "shared",
2815 };
2816
2817 DEFINE_STRING_TABLE_LOOKUP(exec_keyring_mode, ExecKeyringMode);