From: Mike Yuan Date: Sat, 13 Apr 2024 14:42:22 +0000 (+0800) Subject: core/execute: also check cg_is_threaded for clone3() X-Git-Tag: v256-rc1~198^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F32263%2Fhead;p=thirdparty%2Fsystemd.git core/execute: also check cg_is_threaded for clone3() Prompted by #32259 We already have this check in exec_invoke(), i.e. child. But if CLONE_INTO_CGROUP is used, the failure would occur on parent's side, so do the check there too. --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 351b5e40959..c9d968dee0a 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -25,6 +25,7 @@ #include "alloc-util.h" #include "architecture.h" #include "argv-util.h" +#include "cgroup-util.h" #include "dirent-util.h" #include "env-file.h" #include "env-util.h" @@ -2108,7 +2109,13 @@ int posix_spawn_wrapper( return FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP); } - if (!(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r))) + if (ERRNO_IS_NOT_SUPPORTED(r)) { + /* clone3() could also return EOPNOTSUPP if the target cgroup is in threaded mode. */ + if (cgroup && cg_is_threaded(cgroup) > 0) + return -EUCLEAN; + + /* clone3() not available? */ + } else if (!ERRNO_IS_PRIVILEGE(r)) return -r; /* Compiled on a newer host, or seccomp&friends blocking clone3()? Fallback, but need to change the diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index f1e1935e40a..90e11d0d1e9 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -4264,9 +4264,10 @@ int exec_invoke( r = cg_attach_everywhere(params->cgroup_supported, p, 0, NULL, NULL); if (r == -EUCLEAN) { *exit_status = EXIT_CGROUP; - return log_exec_error_errno(context, params, r, "Failed to attach process to cgroup %s " + return log_exec_error_errno(context, params, r, + "Failed to attach process to cgroup '%s', " "because the cgroup or one of its parents or " - "siblings is in the threaded mode: %m", p); + "siblings is in the threaded mode.", p); } if (r < 0) { *exit_status = EXIT_CGROUP; diff --git a/src/core/execute.c b/src/core/execute.c index 0cfbf799461..5a4acd07756 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -456,6 +456,11 @@ int exec_spawn(Unit *unit, environ, cg_unified() > 0 ? subcgroup_path : NULL, &pidref); + if (r == -EUCLEAN && subcgroup_path) + return log_unit_error_errno(unit, r, + "Failed to spawn process into cgroup '%s', because the cgroup " + "or one of its parents or siblings is in the threaded mode.", + subcgroup_path); if (r < 0) return log_unit_error_errno(unit, r, "Failed to spawn executor: %m"); /* We add the new process to the cgroup both in the child (so that we can be sure that no user code is ever