diff options
Diffstat (limited to 'src/core/execute.c')
-rw-r--r-- | src/core/execute.c | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/src/core/execute.c b/src/core/execute.c index 0c2c278d69..1c41b39a2f 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -210,6 +210,50 @@ bool exec_needs_ipc_namespace(const ExecContext *context) { return context->private_ipc || context->ipc_namespace_path; } +static bool can_apply_cgroup_namespace(const ExecContext *context, const ExecParameters *params) { + return cg_all_unified() > 0 && ns_type_supported(NAMESPACE_CGROUP); +} + +static bool needs_cgroup_namespace(ProtectControlGroups i) { + return IN_SET(i, PROTECT_CONTROL_GROUPS_PRIVATE, PROTECT_CONTROL_GROUPS_STRICT); +} + +ProtectControlGroups exec_get_protect_control_groups(const ExecContext *context, const ExecParameters *params) { + assert(context); + + /* If cgroup namespace is configured via ProtectControlGroups=private or strict but we can't actually + * use cgroup namespace, either from not having unified hierarchy or kernel support, we ignore the + * setting and do not unshare the namespace. ProtectControlGroups=private and strict get downgraded + * to no and yes respectively. This ensures that strict always gets a read-only mount of /sys/fs/cgroup. + * + * TODO: Remove fallback once cgroupv1 support is removed in v258. */ + if (needs_cgroup_namespace(context->protect_control_groups) && !can_apply_cgroup_namespace(context, params)) { + if (context->protect_control_groups == PROTECT_CONTROL_GROUPS_PRIVATE) + return PROTECT_CONTROL_GROUPS_NO; + if (context->protect_control_groups == PROTECT_CONTROL_GROUPS_STRICT) + return PROTECT_CONTROL_GROUPS_YES; + } + return context->protect_control_groups; +} + +bool exec_needs_cgroup_namespace(const ExecContext *context, const ExecParameters *params) { + assert(context); + + return needs_cgroup_namespace(exec_get_protect_control_groups(context, params)); +} + +bool exec_needs_cgroup_mount(const ExecContext *context, const ExecParameters *params) { + assert(context); + + return exec_get_protect_control_groups(context, params) != PROTECT_CONTROL_GROUPS_NO; +} + +bool exec_is_cgroup_mount_read_only(const ExecContext *context, const ExecParameters *params) { + assert(context); + + return IN_SET(exec_get_protect_control_groups(context, params), PROTECT_CONTROL_GROUPS_YES, PROTECT_CONTROL_GROUPS_STRICT); +} + bool exec_needs_mount_namespace( const ExecContext *context, const ExecParameters *params, @@ -259,7 +303,7 @@ bool exec_needs_mount_namespace( context->protect_kernel_tunables || context->protect_kernel_modules || context->protect_kernel_logs || - context->protect_control_groups || + exec_needs_cgroup_mount(context, params) || context->protect_proc != PROTECT_PROC_DEFAULT || context->proc_subset != PROC_SUBSET_ALL || exec_needs_ipc_namespace(context)) @@ -287,6 +331,11 @@ bool exec_needs_mount_namespace( if (exec_context_get_effective_bind_log_sockets(context)) return true; + for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) + FOREACH_ARRAY(i, context->directories[t].items, context->directories[t].n_items) + if (FLAGS_SET(i->flags, EXEC_DIRECTORY_READ_ONLY)) + return true; + return false; } @@ -296,7 +345,7 @@ bool exec_directory_is_private(const ExecContext *context, ExecDirectoryType typ if (!context->dynamic_user) return false; - if (type == EXEC_DIRECTORY_CONFIGURATION) + if (!EXEC_DIRECTORY_TYPE_SHALL_CHOWN(type)) return false; if (type == EXEC_DIRECTORY_RUNTIME && context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO) @@ -1000,7 +1049,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { prefix, yes_no(c->protect_kernel_modules), prefix, yes_no(c->protect_kernel_logs), prefix, yes_no(c->protect_clock), - prefix, yes_no(c->protect_control_groups), + prefix, protect_control_groups_to_string(c->protect_control_groups), prefix, yes_no(c->private_network), prefix, private_users_to_string(c->private_users), prefix, protect_home_to_string(c->protect_home), @@ -1074,7 +1123,12 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { fprintf(f, "%s%sMode: %04o\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].mode); for (size_t i = 0; i < c->directories[dt].n_items; i++) { - fprintf(f, "%s%s: %s\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].items[i].path); + fprintf(f, + "%s%s: %s%s\n", + prefix, + exec_directory_type_to_string(dt), + c->directories[dt].items[i].path, + FLAGS_SET(c->directories[dt].items[i].flags, EXEC_DIRECTORY_READ_ONLY) ? " (ro)" : ""); STRV_FOREACH(d, c->directories[dt].items[i].symlinks) fprintf(f, "%s%s: %s:%s\n", prefix, exec_directory_type_symlink_to_string(dt), c->directories[dt].items[i].path, *d); @@ -1595,7 +1649,7 @@ int exec_context_get_clean_directories( return r; /* Also remove private directories unconditionally. */ - if (t != EXEC_DIRECTORY_CONFIGURATION) { + if (EXEC_DIRECTORY_TYPE_SHALL_CHOWN(t)) { j = path_join(prefix[t], "private", i->path); if (!j) return -ENOMEM; @@ -2687,7 +2741,7 @@ static ExecDirectoryItem *exec_directory_find(ExecDirectory *d, const char *path return NULL; } -int exec_directory_add(ExecDirectory *d, const char *path, const char *symlink) { +int exec_directory_add(ExecDirectory *d, const char *path, const char *symlink, ExecDirectoryFlags flags) { _cleanup_strv_free_ char **s = NULL; _cleanup_free_ char *p = NULL; ExecDirectoryItem *existing; @@ -2702,6 +2756,8 @@ int exec_directory_add(ExecDirectory *d, const char *path, const char *symlink) if (r < 0) return r; + existing->flags |= flags; + return 0; /* existing item is updated */ } @@ -2721,6 +2777,7 @@ int exec_directory_add(ExecDirectory *d, const char *path, const char *symlink) d->items[d->n_items++] = (ExecDirectoryItem) { .path = TAKE_PTR(p), .symlinks = TAKE_PTR(s), + .flags = flags, }; return 1; /* new item is added */ @@ -2738,7 +2795,7 @@ void exec_directory_sort(ExecDirectory *d) { /* Sort the exec directories to make always parent directories processed at first in * setup_exec_directory(), e.g., even if StateDirectory=foo/bar foo, we need to create foo at first, - * then foo/bar. Also, set .only_create flag if one of the parent directories is contained in the + * then foo/bar. Also, set the ONLY_CREATE flag if one of the parent directories is contained in the * list. See also comments in setup_exec_directory() and issue #24783. */ if (d->n_items <= 1) @@ -2749,7 +2806,7 @@ void exec_directory_sort(ExecDirectory *d) { for (size_t i = 1; i < d->n_items; i++) for (size_t j = 0; j < i; j++) if (path_startswith(d->items[i].path, d->items[j].path)) { - d->items[i].only_create = true; + d->items[i].flags |= EXEC_DIRECTORY_ONLY_CREATE; break; } } |