diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-03-09 15:10:23 +0100 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-03-27 14:46:57 +0200 |
commit | 28135da3cdca53157bd878ae00b15d6e33ca4987 (patch) | |
tree | 6b88da16d427d0f0ccbda3b7a1153473a69d9e80 /src/core | |
parent | e52a696a9af9e46e6e2be799a344bd9fb34dd3f4 (diff) | |
download | systemd-28135da3cdca53157bd878ae00b15d6e33ca4987.tar.gz |
core: Introduce unit private exec runtime
Currently, exec runtimes can be shared between units (using
JoinsNamespaceOf=). Let's introduce a concept of a private exec
runtime that isn't shared with JoinsNamespaceOf=. The existing
ExecRuntime struct is renamed to ExecRuntimeShared and becomes a
private member of the new private ExecRuntime.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/execute.c | 90 | ||||
-rw-r--r-- | src/core/execute.h | 15 | ||||
-rw-r--r-- | src/core/mount.c | 4 | ||||
-rw-r--r-- | src/core/mount.h | 2 | ||||
-rw-r--r-- | src/core/service.c | 4 | ||||
-rw-r--r-- | src/core/service.h | 2 | ||||
-rw-r--r-- | src/core/socket.c | 19 | ||||
-rw-r--r-- | src/core/socket.h | 2 | ||||
-rw-r--r-- | src/core/swap.c | 4 | ||||
-rw-r--r-- | src/core/swap.h | 2 | ||||
-rw-r--r-- | src/core/unit.c | 33 | ||||
-rw-r--r-- | src/core/unit.h | 2 |
12 files changed, 123 insertions, 56 deletions
diff --git a/src/core/execute.c b/src/core/execute.c index 3011f15dfb..86cfe99e8b 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2178,7 +2178,7 @@ static bool exec_needs_ipc_namespace(const ExecContext *context) { bool exec_needs_mount_namespace( const ExecContext *context, const ExecParameters *params, - const ExecSharedRuntime *runtime) { + const ExecRuntime *runtime) { assert(context); @@ -2210,7 +2210,7 @@ bool exec_needs_mount_namespace( if (!IN_SET(context->mount_propagation_flag, 0, MS_SHARED)) return true; - if (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir)) + if (context->private_tmp && runtime && runtime->shared && (runtime->shared->tmp_dir || runtime->shared->var_tmp_dir)) return true; if (context->private_devices || @@ -3683,7 +3683,7 @@ static int apply_mount_namespace( ExecCommandFlags command_flags, const ExecContext *context, const ExecParameters *params, - const ExecSharedRuntime *runtime, + const ExecRuntime *runtime, const char *memory_pressure_path, char **error_path) { @@ -3742,16 +3742,16 @@ static int apply_mount_namespace( * 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 (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 (context->private_tmp && runtime && runtime->shared) { + if (streq_ptr(runtime->shared->tmp_dir, RUN_SYSTEMD_EMPTY)) + tmp_dir = runtime->shared->tmp_dir; + else if (runtime->shared->tmp_dir) + tmp_dir = strjoina(runtime->shared->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"); + if (streq_ptr(runtime->shared->var_tmp_dir, RUN_SYSTEMD_EMPTY)) + var_tmp_dir = runtime->shared->var_tmp_dir; + else if (runtime->shared->var_tmp_dir) + var_tmp_dir = strjoina(runtime->shared->var_tmp_dir, "/tmp"); } ns_info = (NamespaceInfo) { @@ -4056,7 +4056,7 @@ static void append_socket_pair(int *array, size_t *n, const int pair[static 2]) static int close_remaining_fds( const ExecParameters *params, - const ExecSharedRuntime *runtime, + const ExecRuntime *runtime, const DynamicCreds *dcreds, int user_lookup_fd, int socket_fd, @@ -4081,9 +4081,9 @@ static int close_remaining_fds( n_dont_close += n_fds; } - if (runtime) { - append_socket_pair(dont_close, &n_dont_close, runtime->netns_storage_socket); - append_socket_pair(dont_close, &n_dont_close, runtime->ipcns_storage_socket); + if (runtime && runtime->shared) { + append_socket_pair(dont_close, &n_dont_close, runtime->shared->netns_storage_socket); + append_socket_pair(dont_close, &n_dont_close, runtime->shared->ipcns_storage_socket); } if (dcreds) { @@ -4403,7 +4403,7 @@ static int exec_child( const ExecCommand *command, const ExecContext *context, const ExecParameters *params, - ExecSharedRuntime *runtime, + ExecRuntime *runtime, DynamicCreds *dcreds, const CGroupContext *cgroup_context, int socket_fd, @@ -4686,16 +4686,16 @@ static int exec_child( } } - if (context->network_namespace_path && runtime && runtime->netns_storage_socket[0] >= 0) { - r = open_shareable_ns_path(runtime->netns_storage_socket, context->network_namespace_path, CLONE_NEWNET); + if (context->network_namespace_path && runtime && runtime->shared && runtime->shared->netns_storage_socket[0] >= 0) { + r = open_shareable_ns_path(runtime->shared->netns_storage_socket, context->network_namespace_path, CLONE_NEWNET); if (r < 0) { *exit_status = EXIT_NETWORK; return log_unit_error_errno(unit, r, "Failed to open network namespace path %s: %m", context->network_namespace_path); } } - if (context->ipc_namespace_path && runtime && runtime->ipcns_storage_socket[0] >= 0) { - r = open_shareable_ns_path(runtime->ipcns_storage_socket, context->ipc_namespace_path, CLONE_NEWIPC); + if (context->ipc_namespace_path && runtime && runtime->shared && runtime->shared->ipcns_storage_socket[0] >= 0) { + r = open_shareable_ns_path(runtime->shared->ipcns_storage_socket, context->ipc_namespace_path, CLONE_NEWIPC); if (r < 0) { *exit_status = EXIT_NAMESPACE; return log_unit_error_errno(unit, r, "Failed to open IPC namespace path %s: %m", context->ipc_namespace_path); @@ -5045,10 +5045,10 @@ static int exec_child( } } - if (exec_needs_network_namespace(context) && runtime && runtime->netns_storage_socket[0] >= 0) { + if (exec_needs_network_namespace(context) && runtime && runtime->shared && runtime->shared->netns_storage_socket[0] >= 0) { if (ns_type_supported(NAMESPACE_NET)) { - r = setup_shareable_ns(runtime->netns_storage_socket, CLONE_NEWNET); + r = setup_shareable_ns(runtime->shared->netns_storage_socket, CLONE_NEWNET); if (r < 0) { if (ERRNO_IS_PRIVILEGE(r)) log_unit_warning_errno(unit, r, @@ -5066,10 +5066,10 @@ static int exec_child( log_unit_warning(unit, "PrivateNetwork=yes is configured, but the kernel does not support network namespaces, ignoring."); } - if (exec_needs_ipc_namespace(context) && runtime && runtime->ipcns_storage_socket[0] >= 0) { + if (exec_needs_ipc_namespace(context) && runtime && runtime->shared && runtime->shared->ipcns_storage_socket[0] >= 0) { if (ns_type_supported(NAMESPACE_IPC)) { - r = setup_shareable_ns(runtime->ipcns_storage_socket, CLONE_NEWIPC); + r = setup_shareable_ns(runtime->shared->ipcns_storage_socket, CLONE_NEWIPC); if (r == -EPERM) log_unit_warning_errno(unit, r, "PrivateIPC=yes is configured, but IPC namespace setup failed, ignoring: %m"); @@ -5549,7 +5549,7 @@ int exec_spawn(Unit *unit, ExecCommand *command, const ExecContext *context, const ExecParameters *params, - ExecSharedRuntime *runtime, + ExecRuntime *runtime, DynamicCreds *dcreds, const CGroupContext *cgroup_context, pid_t *ret) { @@ -7439,6 +7439,44 @@ void exec_shared_runtime_vacuum(Manager *m) { } } +int exec_runtime_make(ExecSharedRuntime *shared, ExecRuntime **ret) { + _cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL; + + assert(ret); + + if (!shared) { + *ret = NULL; + return 0; + } + + rt = new(ExecRuntime, 1); + if (!rt) + return -ENOMEM; + + *rt = (ExecRuntime) { + .shared = shared, + }; + + *ret = TAKE_PTR(rt); + return 1; +} + +ExecRuntime* exec_runtime_free(ExecRuntime *rt) { + if (!rt) + return NULL; + + exec_shared_runtime_unref(rt->shared); + return mfree(rt); +} + +ExecRuntime* exec_runtime_destroy(ExecRuntime *rt) { + if (!rt) + return NULL; + + rt->shared = exec_shared_runtime_destroy(rt->shared); + return exec_runtime_free(rt); +} + void exec_params_clear(ExecParameters *p) { if (!p) return; diff --git a/src/core/execute.h b/src/core/execute.h index 10cd2c6046..32ed912f15 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -5,6 +5,7 @@ typedef struct ExecStatus ExecStatus; typedef struct ExecCommand ExecCommand; typedef struct ExecContext ExecContext; typedef struct ExecSharedRuntime ExecSharedRuntime; +typedef struct ExecRuntime ExecRuntime; typedef struct ExecParameters ExecParameters; typedef struct Manager Manager; @@ -124,6 +125,10 @@ struct ExecSharedRuntime { int ipcns_storage_socket[2]; }; +struct ExecRuntime { + ExecSharedRuntime *shared; +}; + typedef enum ExecDirectoryType { EXEC_DIRECTORY_RUNTIME = 0, EXEC_DIRECTORY_STATE, @@ -439,7 +444,7 @@ int exec_spawn(Unit *unit, ExecCommand *command, const ExecContext *context, const ExecParameters *exec_params, - ExecSharedRuntime *runtime, + ExecRuntime *runtime, DynamicCreds *dynamic_creds, const CGroupContext *cgroup_context, pid_t *ret); @@ -486,12 +491,18 @@ void exec_status_reset(ExecStatus *s); int exec_shared_runtime_acquire(Manager *m, const ExecContext *c, const char *name, bool create, ExecSharedRuntime **ret); ExecSharedRuntime *exec_shared_runtime_destroy(ExecSharedRuntime *r); ExecSharedRuntime *exec_shared_runtime_unref(ExecSharedRuntime *r); +DEFINE_TRIVIAL_CLEANUP_FUNC(ExecSharedRuntime*, exec_shared_runtime_unref); int exec_shared_runtime_serialize(const Manager *m, FILE *f, FDSet *fds); int exec_shared_runtime_deserialize_compat(Unit *u, const char *key, const char *value, FDSet *fds); int exec_shared_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds); void exec_shared_runtime_vacuum(Manager *m); +int exec_runtime_make(ExecSharedRuntime *shared, ExecRuntime **ret); +ExecRuntime* exec_runtime_free(ExecRuntime *rt); +DEFINE_TRIVIAL_CLEANUP_FUNC(ExecRuntime*, exec_runtime_free); +ExecRuntime* exec_runtime_destroy(ExecRuntime *rt); + void exec_params_clear(ExecParameters *p); bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c); @@ -533,5 +544,5 @@ ExecDirectoryType exec_directory_type_symlink_from_string(const char *s) _pure_; const char* exec_resource_type_to_string(ExecDirectoryType i) _const_; ExecDirectoryType exec_resource_type_from_string(const char *s) _pure_; -bool exec_needs_mount_namespace(const ExecContext *context, const ExecParameters *params, const ExecSharedRuntime *runtime); +bool exec_needs_mount_namespace(const ExecContext *context, const ExecParameters *params, const ExecRuntime *runtime); bool exec_needs_network_namespace(const ExecContext *context); diff --git a/src/core/mount.c b/src/core/mount.c index e755a55964..a8a677a531 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -254,7 +254,7 @@ static void mount_done(Unit *u) { mount_parameters_done(&m->parameters_proc_self_mountinfo); mount_parameters_done(&m->parameters_fragment); - m->exec_runtime = exec_shared_runtime_unref(m->exec_runtime); + m->exec_runtime = exec_runtime_free(m->exec_runtime); exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX); m->control_command = NULL; @@ -948,7 +948,7 @@ static void mount_enter_dead(Mount *m, MountResult f) { mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); - m->exec_runtime = exec_shared_runtime_destroy(m->exec_runtime); + m->exec_runtime = exec_runtime_destroy(m->exec_runtime); unit_destroy_runtime_data(UNIT(m), &m->exec_context); diff --git a/src/core/mount.h b/src/core/mount.h index 39d7247170..1a0d9fc5e5 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -75,7 +75,7 @@ struct Mount { KillContext kill_context; CGroupContext cgroup_context; - ExecSharedRuntime *exec_runtime; + ExecRuntime *exec_runtime; DynamicCreds dynamic_creds; MountState state, deserialized_state; diff --git a/src/core/service.c b/src/core/service.c index 4894d94511..883c4bbd93 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -383,7 +383,7 @@ static void service_done(Unit *u) { s->pid_file = mfree(s->pid_file); s->status_text = mfree(s->status_text); - s->exec_runtime = exec_shared_runtime_unref(s->exec_runtime); + s->exec_runtime = exec_runtime_free(s->exec_runtime); exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX); s->control_command = NULL; s->main_command = NULL; @@ -1925,7 +1925,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) s->notify_access_override = _NOTIFY_ACCESS_INVALID; /* We want fresh tmpdirs in case service is started again immediately */ - s->exec_runtime = exec_shared_runtime_destroy(s->exec_runtime); + s->exec_runtime = exec_runtime_destroy(s->exec_runtime); /* Also, remove the runtime directory */ unit_destroy_runtime_data(UNIT(s), &s->exec_context); diff --git a/src/core/service.h b/src/core/service.h index 92eeef4a7b..7663f26f70 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -155,7 +155,7 @@ struct Service { ServiceExecCommand control_command_id; /* Runtime data of the execution context */ - ExecSharedRuntime *exec_runtime; + ExecRuntime *exec_runtime; DynamicCreds dynamic_creds; pid_t main_pid, control_pid; diff --git a/src/core/socket.c b/src/core/socket.c index 0e33c41def..163fc0bebf 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -150,7 +150,7 @@ static void socket_done(Unit *u) { s->peers_by_address = set_free(s->peers_by_address); - s->exec_runtime = exec_shared_runtime_unref(s->exec_runtime); + s->exec_runtime = exec_runtime_free(s->exec_runtime); exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); s->control_command = NULL; @@ -1532,16 +1532,18 @@ static int socket_address_listen_in_cgroup( if (s->exec_context.network_namespace_path && s->exec_runtime && - s->exec_runtime->netns_storage_socket[0] >= 0) { - r = open_shareable_ns_path(s->exec_runtime->netns_storage_socket, s->exec_context.network_namespace_path, CLONE_NEWNET); + s->exec_runtime->shared && + s->exec_runtime->shared->netns_storage_socket[0] >= 0) { + r = open_shareable_ns_path(s->exec_runtime->shared->netns_storage_socket, s->exec_context.network_namespace_path, CLONE_NEWNET); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to open network namespace path %s: %m", s->exec_context.network_namespace_path); } if (s->exec_context.ipc_namespace_path && s->exec_runtime && - s->exec_runtime->ipcns_storage_socket[0] >= 0) { - r = open_shareable_ns_path(s->exec_runtime->ipcns_storage_socket, s->exec_context.ipc_namespace_path, CLONE_NEWIPC); + s->exec_runtime->shared && + s->exec_runtime->shared->ipcns_storage_socket[0] >= 0) { + r = open_shareable_ns_path(s->exec_runtime->shared->ipcns_storage_socket, s->exec_context.ipc_namespace_path, CLONE_NEWIPC); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to open IPC namespace path %s: %m", s->exec_context.ipc_namespace_path); } @@ -1559,10 +1561,11 @@ static int socket_address_listen_in_cgroup( if (exec_needs_network_namespace(&s->exec_context) && s->exec_runtime && - s->exec_runtime->netns_storage_socket[0] >= 0) { + s->exec_runtime->shared && + s->exec_runtime->shared->netns_storage_socket[0] >= 0) { if (ns_type_supported(NAMESPACE_NET)) { - r = setup_shareable_ns(s->exec_runtime->netns_storage_socket, CLONE_NEWNET); + r = setup_shareable_ns(s->exec_runtime->shared->netns_storage_socket, CLONE_NEWNET); if (r < 0) { log_unit_error_errno(UNIT(s), r, "Failed to join network namespace: %m"); _exit(EXIT_NETWORK); @@ -2049,7 +2052,7 @@ static void socket_enter_dead(Socket *s, SocketResult f) { socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); - s->exec_runtime = exec_shared_runtime_destroy(s->exec_runtime); + s->exec_runtime = exec_runtime_destroy(s->exec_runtime); unit_destroy_runtime_data(UNIT(s), &s->exec_context); diff --git a/src/core/socket.h b/src/core/socket.h index af65009ab8..6813bdcf8c 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -90,7 +90,7 @@ struct Socket { KillContext kill_context; CGroupContext cgroup_context; - ExecSharedRuntime *exec_runtime; + ExecRuntime *exec_runtime; DynamicCreds dynamic_creds; /* For Accept=no sockets refers to the one service we'll diff --git a/src/core/swap.c b/src/core/swap.c index 7b33060ab8..17f8123055 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -170,7 +170,7 @@ static void swap_done(Unit *u) { s->parameters_fragment.what = mfree(s->parameters_fragment.what); s->parameters_fragment.options = mfree(s->parameters_fragment.options); - s->exec_runtime = exec_shared_runtime_unref(s->exec_runtime); + s->exec_runtime = exec_runtime_free(s->exec_runtime); exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX); s->control_command = NULL; @@ -719,7 +719,7 @@ static void swap_enter_dead(Swap *s, SwapResult f) { unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop); swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD); - s->exec_runtime = exec_shared_runtime_destroy(s->exec_runtime); + s->exec_runtime = exec_runtime_destroy(s->exec_runtime); unit_destroy_runtime_data(UNIT(s), &s->exec_context); diff --git a/src/core/swap.h b/src/core/swap.h index 49cd82c591..c0e3f118e1 100644 --- a/src/core/swap.h +++ b/src/core/swap.h @@ -67,7 +67,7 @@ struct Swap { KillContext kill_context; CGroupContext cgroup_context; - ExecSharedRuntime *exec_runtime; + ExecRuntime *exec_runtime; DynamicCreds dynamic_creds; SwapState state, deserialized_state; diff --git a/src/core/unit.c b/src/core/unit.c index 25e2509f51..e569a82e1c 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4268,7 +4268,7 @@ CGroupContext *unit_get_cgroup_context(Unit *u) { return (CGroupContext*) ((uint8_t*) u + offset); } -ExecSharedRuntime *unit_get_exec_runtime(Unit *u) { +ExecRuntime *unit_get_exec_runtime(Unit *u) { size_t offset; if (u->type < 0) @@ -4278,7 +4278,7 @@ ExecSharedRuntime *unit_get_exec_runtime(Unit *u) { if (offset <= 0) return NULL; - return *(ExecSharedRuntime**) ((uint8_t*) u + offset); + return *(ExecRuntime**) ((uint8_t*) u + offset); } static const char* unit_drop_in_dir(Unit *u, UnitWriteFlags flags) { @@ -4791,7 +4791,8 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) } int unit_setup_exec_runtime(Unit *u) { - ExecSharedRuntime **rt; + _cleanup_(exec_shared_runtime_unrefp) ExecSharedRuntime *esr = NULL; + ExecRuntime **rt; size_t offset; Unit *other; int r; @@ -4799,19 +4800,33 @@ int unit_setup_exec_runtime(Unit *u) { offset = UNIT_VTABLE(u)->exec_runtime_offset; assert(offset > 0); - /* Check if there already is an ExecSharedRuntime for this unit? */ - rt = (ExecSharedRuntime**) ((uint8_t*) u + offset); + /* Check if there already is an ExecRuntime for this unit? */ + rt = (ExecRuntime**) ((uint8_t*) u + offset); if (*rt) return 0; /* Try to get it from somebody else */ UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_JOINS_NAMESPACE_OF) { - r = exec_shared_runtime_acquire(u->manager, NULL, other->id, false, rt); - if (r == 1) - return 1; + r = exec_shared_runtime_acquire(u->manager, NULL, other->id, false, &esr); + if (r < 0) + return r; + if (r > 0) + break; + } + + if (!esr) { + r = exec_shared_runtime_acquire(u->manager, unit_get_exec_context(u), u->id, true, &esr); + if (r < 0) + return r; } - return exec_shared_runtime_acquire(u->manager, unit_get_exec_context(u), u->id, true, rt); + r = exec_runtime_make(esr, rt); + if (r < 0) + return r; + + TAKE_PTR(esr); + + return r; } int unit_setup_dynamic_creds(Unit *u) { diff --git a/src/core/unit.h b/src/core/unit.h index 19a50ac690..bf9aea578a 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -964,7 +964,7 @@ ExecContext *unit_get_exec_context(const Unit *u) _pure_; KillContext *unit_get_kill_context(Unit *u) _pure_; CGroupContext *unit_get_cgroup_context(Unit *u) _pure_; -ExecSharedRuntime *unit_get_exec_runtime(Unit *u) _pure_; +ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_; int unit_setup_exec_runtime(Unit *u); int unit_setup_dynamic_creds(Unit *u); |