static bool context_has_address_families(const ExecContext *c) {
assert(c);
- return c->address_families_whitelist ||
+ return c->address_families_allow_list ||
!set_isempty(c->address_families);
}
static bool context_has_syscall_filters(const ExecContext *c) {
assert(c);
- return c->syscall_whitelist ||
+ return c->syscall_allow_list ||
!hashmap_isempty(c->syscall_filter);
}
negative_action = c->syscall_errno == 0 ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno);
- if (c->syscall_whitelist) {
+ if (c->syscall_allow_list) {
default_action = negative_action;
action = SCMP_ACT_ALLOW;
} else {
}
if (needs_ambient_hack) {
- r = seccomp_filter_set_add(c->syscall_filter, c->syscall_whitelist, syscall_filter_sets + SYSCALL_FILTER_SET_SETUID);
+ r = seccomp_filter_set_add(c->syscall_filter, c->syscall_allow_list, syscall_filter_sets + SYSCALL_FILTER_SET_SETUID);
if (r < 0)
return r;
}
if (skip_seccomp_unavailable(u, "RestrictAddressFamilies="))
return 0;
- return seccomp_restrict_address_families(c->address_families, c->address_families_whitelist);
+ return seccomp_restrict_address_families(c->address_families, c->address_families_allow_list);
}
static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) {
assert(p);
assert(ret);
- our_env = new0(char*, 15 + _EXEC_DIRECTORY_TYPE_MAX);
+#define N_ENV_VARS 15
+ our_env = new0(char*, N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX);
if (!our_env)
return -ENOMEM;
}
our_env[n_env++] = NULL;
- assert(n_env <= 14 + _EXEC_DIRECTORY_TYPE_MAX);
+ assert(n_env <= N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX);
+#undef N_ENV_VARS
*ret = TAKE_PTR(our_env);
char **error_path) {
_cleanup_strv_free_ char **empty_directories = NULL;
- char *tmp = NULL, *var = NULL;
+ const char *tmp_dir = NULL, *var_tmp_dir = NULL;
const char *root_dir = NULL, *root_image = NULL;
NamespaceInfo ns_info;
bool needs_sandboxing;
if (needs_sandboxing) {
/* The runtime struct only contains the parent of the private /tmp,
* which is non-accessible to world users. Inside of it there's a /tmp
- * that is sticky, and that's the one we want to use here. */
+ * that is sticky, and that's the one we want to use here.
+ * This does not apply when we are using /run/systemd/empty as fallback. */
if (context->private_tmp && runtime) {
- if (runtime->tmp_dir)
- tmp = strjoina(runtime->tmp_dir, "/tmp");
- if (runtime->var_tmp_dir)
- var = strjoina(runtime->var_tmp_dir, "/tmp");
+ if (streq_ptr(runtime->tmp_dir, RUN_SYSTEMD_EMPTY))
+ tmp_dir = runtime->tmp_dir;
+ else if (runtime->tmp_dir)
+ tmp_dir = strjoina(runtime->tmp_dir, "/tmp");
+
+ if (streq_ptr(runtime->var_tmp_dir, RUN_SYSTEMD_EMPTY))
+ var_tmp_dir = runtime->var_tmp_dir;
+ else if (runtime->var_tmp_dir)
+ var_tmp_dir = strjoina(runtime->var_tmp_dir, "/tmp");
}
ns_info = (NamespaceInfo) {
if (context->mount_flags == MS_SHARED)
log_unit_debug(u, "shared mount propagation hidden by other fs namespacing unit settings: ignoring");
- r = setup_namespace(root_dir, root_image,
+ r = setup_namespace(root_dir, root_image, context->root_image_options,
&ns_info, context->read_write_paths,
needs_sandboxing ? context->read_only_paths : NULL,
needs_sandboxing ? context->inaccessible_paths : NULL,
n_bind_mounts,
context->temporary_filesystems,
context->n_temporary_filesystems,
- tmp,
- var,
+ tmp_dir,
+ var_tmp_dir,
context->log_namespace,
needs_sandboxing ? context->protect_home : PROTECT_HOME_NO,
needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO,
context->mount_flags,
- context->root_hash, context->root_hash_size, context->root_hash_path, context->root_verity,
+ context->root_hash, context->root_hash_size, context->root_hash_path,
+ context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path,
+ context->root_verity,
DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
error_path);
}
out:
- /* Revert back uid & gid for the the last time, and exit */
+ /* Revert back uid & gid for the last time, and exit */
/* no extra logging, as only the first already reported error matters */
if (getuid() != saved_uid)
(void) setreuid(saved_uid, -1);
c->working_directory = mfree(c->working_directory);
c->root_directory = mfree(c->root_directory);
c->root_image = mfree(c->root_image);
+ c->root_image_options = mount_options_free_all(c->root_image_options);
c->root_hash = mfree(c->root_hash);
c->root_hash_size = 0;
c->root_hash_path = mfree(c->root_hash_path);
+ c->root_hash_sig = mfree(c->root_hash_sig);
+ c->root_hash_sig_size = 0;
+ c->root_hash_sig_path = mfree(c->root_hash_sig_path);
c->root_verity = mfree(c->root_verity);
c->tty_path = mfree(c->tty_path);
c->syslog_identifier = mfree(c->syslog_identifier);
if (c->root_image)
fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
+ if (c->root_image_options) {
+ MountOptions *o;
+
+ fprintf(f, "%sRootImageOptions:", prefix);
+ LIST_FOREACH(mount_options, o, c->root_image_options)
+ if (!isempty(o->options))
+ fprintf(f, " %u:%s", o->partition_number, o->options);
+ fprintf(f, "\n");
+ }
+
if (c->root_hash) {
_cleanup_free_ char *encoded = NULL;
encoded = hexmem(c->root_hash, c->root_hash_size);
if (c->root_hash_path)
fprintf(f, "%sRootHash: %s\n", prefix, c->root_hash_path);
+ if (c->root_hash_sig) {
+ _cleanup_free_ char *encoded = NULL;
+ ssize_t len;
+ len = base64mem(c->root_hash_sig, c->root_hash_sig_size, &encoded);
+ if (len)
+ fprintf(f, "%sRootHashSignature: base64:%s\n", prefix, encoded);
+ }
+
+ if (c->root_hash_sig_path)
+ fprintf(f, "%sRootHashSignature: %s\n", prefix, c->root_hash_sig_path);
+
if (c->root_verity)
fprintf(f, "%sRootVerity: %s\n", prefix, c->root_verity);
"%sSystemCallFilter: ",
prefix);
- if (!c->syscall_whitelist)
+ if (!c->syscall_allow_list)
fputc('~', f);
#if HAVE_SECCOMP
(void) hashmap_remove(rt->manager->exec_runtime_by_id, rt->id);
/* When destroy is true, then rm_rf tmp_dir and var_tmp_dir. */
- if (destroy && rt->tmp_dir) {
+
+ if (destroy && rt->tmp_dir && !streq(rt->tmp_dir, RUN_SYSTEMD_EMPTY)) {
log_debug("Spawning thread to nuke %s", rt->tmp_dir);
r = asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
- if (r < 0) {
+ if (r < 0)
log_warning_errno(r, "Failed to nuke %s: %m", rt->tmp_dir);
- free(rt->tmp_dir);
- }
-
- rt->tmp_dir = NULL;
+ else
+ rt->tmp_dir = NULL;
}
- if (destroy && rt->var_tmp_dir) {
+ if (destroy && rt->var_tmp_dir && !streq(rt->var_tmp_dir, RUN_SYSTEMD_EMPTY)) {
log_debug("Spawning thread to nuke %s", rt->var_tmp_dir);
r = asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
- if (r < 0) {
+ if (r < 0)
log_warning_errno(r, "Failed to nuke %s: %m", rt->var_tmp_dir);
- free(rt->var_tmp_dir);
- }
-
- rt->var_tmp_dir = NULL;
+ else
+ rt->var_tmp_dir = NULL;
}
rt->id = mfree(rt->id);
(void) exec_runtime_free(*rt, false);
}
-static int exec_runtime_allocate(ExecRuntime **ret) {
+static int exec_runtime_allocate(ExecRuntime **ret, const char *id) {
+ _cleanup_free_ char *id_copy = NULL;
ExecRuntime *n;
assert(ret);
+ id_copy = strdup(id);
+ if (!id_copy)
+ return -ENOMEM;
+
n = new(ExecRuntime, 1);
if (!n)
return -ENOMEM;
*n = (ExecRuntime) {
+ .id = TAKE_PTR(id_copy),
.netns_storage_socket = { -1, -1 },
};
static int exec_runtime_add(
Manager *m,
const char *id,
- const char *tmp_dir,
- const char *var_tmp_dir,
- const int netns_storage_socket[2],
+ char **tmp_dir,
+ char **var_tmp_dir,
+ int netns_storage_socket[2],
ExecRuntime **ret) {
_cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL;
assert(m);
assert(id);
+ /* tmp_dir, var_tmp_dir, netns_storage_socket fds are donated on success */
+
r = hashmap_ensure_allocated(&m->exec_runtime_by_id, &string_hash_ops);
if (r < 0)
return r;
- r = exec_runtime_allocate(&rt);
+ r = exec_runtime_allocate(&rt, id);
if (r < 0)
return r;
- rt->id = strdup(id);
- if (!rt->id)
- return -ENOMEM;
-
- if (tmp_dir) {
- rt->tmp_dir = strdup(tmp_dir);
- if (!rt->tmp_dir)
- return -ENOMEM;
+ r = hashmap_put(m->exec_runtime_by_id, rt->id, rt);
+ if (r < 0)
+ return r;
- /* When tmp_dir is set, then we require var_tmp_dir is also set. */
- assert(var_tmp_dir);
- rt->var_tmp_dir = strdup(var_tmp_dir);
- if (!rt->var_tmp_dir)
- return -ENOMEM;
- }
+ assert(!!rt->tmp_dir == !!rt->var_tmp_dir); /* We require both to be set together */
+ rt->tmp_dir = TAKE_PTR(*tmp_dir);
+ rt->var_tmp_dir = TAKE_PTR(*var_tmp_dir);
if (netns_storage_socket) {
- rt->netns_storage_socket[0] = netns_storage_socket[0];
- rt->netns_storage_socket[1] = netns_storage_socket[1];
+ rt->netns_storage_socket[0] = TAKE_FD(netns_storage_socket[0]);
+ rt->netns_storage_socket[1] = TAKE_FD(netns_storage_socket[1]);
}
- r = hashmap_put(m->exec_runtime_by_id, rt->id, rt);
- if (r < 0)
- return r;
-
rt->manager = m;
if (ret)
*ret = rt;
-
/* do not remove created ExecRuntime object when the operation succeeds. */
- rt = NULL;
+ TAKE_PTR(rt);
return 0;
}
static int exec_runtime_make(Manager *m, const ExecContext *c, const char *id, ExecRuntime **ret) {
- _cleanup_free_ char *tmp_dir = NULL, *var_tmp_dir = NULL;
+ _cleanup_(namespace_cleanup_tmpdirp) char *tmp_dir = NULL, *var_tmp_dir = NULL;
_cleanup_close_pair_ int netns_storage_socket[2] = { -1, -1 };
int r;
return -errno;
}
- r = exec_runtime_add(m, id, tmp_dir, var_tmp_dir, netns_storage_socket, ret);
+ r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_storage_socket, ret);
if (r < 0)
return r;
- /* Avoid cleanup */
- netns_storage_socket[0] = netns_storage_socket[1] = -1;
return 1;
}
rt = hashmap_get(u->manager->exec_runtime_by_id, u->id);
if (!rt) {
- r = exec_runtime_allocate(&rt_create);
+ r = exec_runtime_allocate(&rt_create, u->id);
if (r < 0)
return log_oom();
- rt_create->id = strdup(u->id);
- if (!rt_create->id)
- return log_oom();
-
rt = rt_create;
}
rt_create->manager = u->manager;
/* Avoid cleanup */
- rt_create = NULL;
+ TAKE_PTR(rt_create);
}
return 1;
}
-void exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
- char *id = NULL, *tmp_dir = NULL, *var_tmp_dir = NULL;
- int r, fd0 = -1, fd1 = -1;
+int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
+ _cleanup_free_ char *tmp_dir = NULL, *var_tmp_dir = NULL;
+ char *id = NULL;
+ int r, fdpair[] = {-1, -1};
const char *p, *v = value;
size_t n;
v = startswith(p, "tmp-dir=");
if (v) {
n = strcspn(v, " ");
- tmp_dir = strndupa(v, n);
+ tmp_dir = strndup(v, n);
+ if (!tmp_dir)
+ return log_oom();
if (v[n] != ' ')
goto finalize;
p = v + n + 1;
v = startswith(p, "var-tmp-dir=");
if (v) {
n = strcspn(v, " ");
- var_tmp_dir = strndupa(v, n);
+ var_tmp_dir = strndup(v, n);
+ if (!var_tmp_dir)
+ return log_oom();
if (v[n] != ' ')
goto finalize;
p = v + n + 1;
n = strcspn(v, " ");
buf = strndupa(v, n);
- if (safe_atoi(buf, &fd0) < 0 || !fdset_contains(fds, fd0)) {
- log_debug("Unable to process exec-runtime netns fd specification.");
- return;
- }
- fd0 = fdset_remove(fds, fd0);
+ if (safe_atoi(buf, &fdpair[0]) < 0 || !fdset_contains(fds, fdpair[0]))
+ return log_debug("Unable to process exec-runtime netns fd specification.");
+ fdpair[0] = fdset_remove(fds, fdpair[0]);
if (v[n] != ' ')
goto finalize;
p = v + n + 1;
n = strcspn(v, " ");
buf = strndupa(v, n);
- if (safe_atoi(buf, &fd1) < 0 || !fdset_contains(fds, fd1)) {
- log_debug("Unable to process exec-runtime netns fd specification.");
- return;
- }
- fd1 = fdset_remove(fds, fd1);
+ if (safe_atoi(buf, &fdpair[1]) < 0 || !fdset_contains(fds, fdpair[1]))
+ return log_debug("Unable to process exec-runtime netns fd specification.");
+ fdpair[1] = fdset_remove(fds, fdpair[1]);
}
finalize:
-
- r = exec_runtime_add(m, id, tmp_dir, var_tmp_dir, (int[]) { fd0, fd1 }, NULL);
+ r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, fdpair, NULL);
if (r < 0)
- log_debug_errno(r, "Failed to add exec-runtime: %m");
+ return log_debug_errno(r, "Failed to add exec-runtime: %m");
+ return 0;
}
void exec_runtime_vacuum(Manager *m) {
if (!p)
return;
- strv_free(p->environment);
+ p->environment = strv_free(p->environment);
+ p->fd_names = strv_free(p->fd_names);
+ p->fds = mfree(p->fds);
+ p->exec_fd = safe_close(p->exec_fd);
}
static const char* const exec_input_table[_EXEC_INPUT_MAX] = {