From: Daan De Meyer Date: Fri, 21 Mar 2025 08:41:15 +0000 (+0100) Subject: core: Disable pid namespacing for control processes X-Git-Tag: v258-rc1~379^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d8191f4af416a7c7042353121e3ae3f93b56f4d;p=thirdparty%2Fsystemd.git core: Disable pid namespacing for control processes PID namespaces frankly don't make any sense for control processes, so let's gracefully degrade to no pid namespaces for control processes. --- diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 6b69f5666ab..a9c8664c4a2 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -3541,7 +3541,7 @@ static int apply_mount_namespace( .private_dev = needs_sandboxing && context->private_devices, .private_network = needs_sandboxing && exec_needs_network_namespace(context), .private_ipc = needs_sandboxing && exec_needs_ipc_namespace(context), - .private_pids = needs_sandboxing && exec_needs_pid_namespace(context) ? context->private_pids : PRIVATE_PIDS_NO, + .private_pids = needs_sandboxing && exec_needs_pid_namespace(context, params) ? context->private_pids : PRIVATE_PIDS_NO, .private_tmp = needs_sandboxing ? context->private_tmp : PRIVATE_TMP_NO, .private_var_tmp = needs_sandboxing ? context->private_var_tmp : PRIVATE_TMP_NO, @@ -4102,7 +4102,7 @@ static void log_command_line( LOG_EXEC_INVOCATION_ID(params)); } -static bool exec_context_needs_cap_sys_admin(const ExecContext *context) { +static bool exec_needs_cap_sys_admin(const ExecContext *context, const ExecParameters *params) { assert(context); return context->private_users != PRIVATE_USERS_NO || @@ -4121,7 +4121,7 @@ static bool exec_context_needs_cap_sys_admin(const ExecContext *context) { !strv_isempty(context->extension_directories) || context->protect_system != PROTECT_SYSTEM_NO || context->protect_home != PROTECT_HOME_NO || - exec_needs_pid_namespace(context) || + exec_needs_pid_namespace(context, params) || context->protect_kernel_tunables || context->protect_kernel_modules || context->protect_kernel_logs || @@ -4166,7 +4166,7 @@ static bool exec_namespace_is_delegated( /* If we need unprivileged private users, we've already unshared a user namespace by the time we call * setup_delegated_namespaces() for the first time so let's make sure we do all other namespace * unsharing in the first call to setup_delegated_namespaces() by returning false here. */ - if (!have_cap_sys_admin && exec_context_needs_cap_sys_admin(context)) + if (!have_cap_sys_admin && exec_needs_cap_sys_admin(context, params)) return false; if (context->delegate_namespaces == NAMESPACE_FLAGS_INITIAL) @@ -4269,7 +4269,7 @@ static int setup_delegated_namespaces( /* Unshare a new PID namespace before setting up mounts to ensure /proc/ is mounted with only processes in PID namespace visible. * Note PrivatePIDs=yes implies MountAPIVFS=yes so we'll always ensure procfs is remounted. */ - if (needs_sandboxing && exec_needs_pid_namespace(context) && + if (needs_sandboxing && exec_needs_pid_namespace(context, params) && exec_namespace_is_delegated(context, params, have_cap_sys_admin, CLONE_NEWPID) == delegate) { if (params->pidref_transport_fd < 0) { *reterr_exit_status = EXIT_NAMESPACE; @@ -5352,7 +5352,7 @@ int exec_invoke( } } - if (needs_sandboxing && !have_cap_sys_admin && exec_context_needs_cap_sys_admin(context)) { + if (needs_sandboxing && !have_cap_sys_admin && exec_needs_cap_sys_admin(context, params)) { /* If we're unprivileged, set up the user namespace first to enable use of the other namespaces. * Users with CAP_SYS_ADMIN can set up user namespaces last because they will be able to * set up all of the other namespaces (i.e. network, mount, UTS) without a user namespace. */ diff --git a/src/core/execute.c b/src/core/execute.c index 2e5303987cb..31b5e13fe4a 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -262,9 +262,13 @@ bool exec_is_cgroup_mount_read_only(const ExecContext *context) { return IN_SET(exec_get_protect_control_groups(context), PROTECT_CONTROL_GROUPS_YES, PROTECT_CONTROL_GROUPS_STRICT); } -bool exec_needs_pid_namespace(const ExecContext *context) { +bool exec_needs_pid_namespace(const ExecContext *context, const ExecParameters *params) { assert(context); + /* PID namespaces don't really make sense for control processes so let's not use them for those. */ + if (params && FLAGS_SET(params->flags, EXEC_IS_CONTROL)) + return false; + return context->private_pids != PRIVATE_PIDS_NO && namespace_type_supported(NAMESPACE_PID); } @@ -321,7 +325,7 @@ bool exec_needs_mount_namespace( context->protect_proc != PROTECT_PROC_DEFAULT || context->proc_subset != PROC_SUBSET_ALL || exec_needs_ipc_namespace(context) || - exec_needs_pid_namespace(context)) + exec_needs_pid_namespace(context, params)) return true; if (context->root_directory) { diff --git a/src/core/execute.h b/src/core/execute.h index 5700e7febe5..fba08627391 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -595,7 +595,7 @@ ExecDirectoryType exec_resource_type_from_string(const char *s) _pure_; bool exec_needs_mount_namespace(const ExecContext *context, const ExecParameters *params, const ExecRuntime *runtime); bool exec_needs_network_namespace(const ExecContext *context); bool exec_needs_ipc_namespace(const ExecContext *context); -bool exec_needs_pid_namespace(const ExecContext *context); +bool exec_needs_pid_namespace(const ExecContext *context, const ExecParameters *params); ProtectControlGroups exec_get_protect_control_groups(const ExecContext *context); bool exec_needs_cgroup_namespace(const ExecContext *context); diff --git a/src/core/service.c b/src/core/service.c index 295691fd0df..5f03a462ec6 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -702,7 +702,7 @@ static int service_verify(Service *s) { if (s->type == SERVICE_DBUS && !s->bus_name) return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Service is of type D-Bus but no D-Bus service name has been specified. Refusing."); - if (s->type == SERVICE_FORKING && exec_needs_pid_namespace(&s->exec_context)) + if (s->type == SERVICE_FORKING && exec_needs_pid_namespace(&s->exec_context, /* params= */ NULL)) return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC), "Service of Type=forking does not support PrivatePIDs=yes. Refusing."); if (s->usb_function_descriptors && !s->usb_function_strings) diff --git a/src/core/unit.c b/src/core/unit.c index d617624dede..1397b7bf38f 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4252,7 +4252,7 @@ static int unit_verify_contexts(const Unit *u) { exec_needs_mount_namespace(ec, /* params = */ NULL, /* runtime = */ NULL)) return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOEXEC), "WorkingDirectory= may not be below /proc/, /sys/ or /dev/ when using mount namespacing. Refusing."); - if (exec_needs_pid_namespace(ec) && !UNIT_VTABLE(u)->notify_pidref) + if (exec_needs_pid_namespace(ec, /* params= */ NULL) && !UNIT_VTABLE(u)->notify_pidref) return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOEXEC), "PrivatePIDs= setting is only supported for service units. Refusing."); const KillContext *kc = unit_get_kill_context(u);