]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add serialization/deserialization for ExecParameters
authorLuca Boccassi <bluca@debian.org>
Thu, 31 Aug 2023 23:40:37 +0000 (00:40 +0100)
committerLuca Boccassi <bluca@debian.org>
Thu, 12 Oct 2023 13:57:38 +0000 (14:57 +0100)
src/core/execute-serialize.c
src/core/execute-serialize.h
src/core/execute.h
src/core/unit.c

index 2d3445e01a98a96711be49a67e84e2283cc8c89c..ad6275908ce458ab2d6993123cb7a99a899a6fe3 100644 (file)
 #include "string-util.h"
 #include "strv.h"
 
+static int exec_parameters_serialize(const ExecParameters *p, FILE *f, FDSet *fds) {
+        int r;
+
+        assert(f);
+        assert(fds);
+
+        if (!p)
+                return 0;
+
+        r = serialize_item(f, "exec-parameters-runtime-scope", runtime_scope_to_string(p->runtime_scope));
+        if (r < 0)
+                return r;
+
+        r = serialize_strv(f, "exec-parameters-environment", p->environment);
+        if (r < 0)
+                return r;
+
+        if (p->n_socket_fds) {
+                r = serialize_item_format(f, "exec-parameters-n-socket-fds", "%zu", p->n_socket_fds);
+                if (r < 0)
+                        return r;
+        }
+
+        if (p->n_storage_fds) {
+                r = serialize_item_format(f, "exec-parameters-n-storage-fds", "%zu", p->n_storage_fds);
+                if (r < 0)
+                        return r;
+        }
+
+        if (p->n_socket_fds + p->n_storage_fds > 0) {
+                _cleanup_free_ char *serialized_fds = NULL;
+
+                if (!p->fds)
+                        return -EINVAL;
+
+                for (size_t i = 0; i < p->n_socket_fds + p->n_storage_fds; ++i) {
+                        int copy = -EBADF;
+
+                        if (p->fds[i] >= 0) {
+                                copy = fdset_put_dup(fds, p->fds[i]);
+                                if (copy < 0)
+                                        return copy;
+                        }
+
+                        r = strextendf(&serialized_fds, "%d ", copy);
+                        if (r < 0)
+                                return r;
+                }
+
+                r = serialize_item(f, "exec-parameters-fds", serialized_fds);
+                if (r < 0)
+                        return r;
+        }
+
+        r = serialize_strv(f, "exec-parameters-fd-names", p->fd_names);
+        if (r < 0)
+                return r;
+
+        if (p->flags != 0) {
+                r = serialize_item_format(f, "exec-parameters-flags", "%u", (unsigned) p->flags);
+                if (r < 0)
+                        return r;
+        }
+
+        r = serialize_bool_elide(f, "exec-parameters-selinux-context-net", p->selinux_context_net);
+        if (r < 0)
+                return r;
+
+        if (p->cgroup_supported != 0) {
+                r = serialize_item_format(f, "exec-parameters-cgroup-supported", "%u", (unsigned) p->cgroup_supported);
+                if (r < 0)
+                        return r;
+        }
+
+        r = serialize_item(f, "exec-parameters-cgroup-path", p->cgroup_path);
+        if (r < 0)
+                return r;
+
+        r = serialize_item_format(f, "exec-parameters-cgroup-id", "%" PRIu64, p->cgroup_id);
+        if (r < 0)
+                return r;
+
+        for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) {
+                _cleanup_free_ char *key = NULL;
+
+                key = strjoin("exec-parameters-prefix-directories-", exec_directory_type_to_string(dt));
+                if (!key)
+                        return log_oom_debug();
+
+                /* Always serialize, even an empty prefix, as this is a fixed array and we always expect
+                 * to have all elements (unless fuzzing is happening, hence the NULL check). */
+                r = serialize_item(f, key, strempty(p->prefix ? p->prefix[dt] : NULL));
+                if (r < 0)
+                        return r;
+        }
+
+        r = serialize_item(f, "exec-parameters-received-credentials-directory", p->received_credentials_directory);
+        if (r < 0)
+                return r;
+
+        r = serialize_item(f, "exec-parameters-received-encrypted-credentials-directory", p->received_encrypted_credentials_directory);
+        if (r < 0)
+                return r;
+
+        r = serialize_item(f, "exec-parameters-confirm-spawn", p->confirm_spawn);
+        if (r < 0)
+                return r;
+
+        r = serialize_bool_elide(f, "exec-parameters-shall-confirm-spawn", p->shall_confirm_spawn);
+        if (r < 0)
+                return r;
+
+        if (p->watchdog_usec > 0) {
+                r = serialize_usec(f, "exec-parameters-watchdog-usec", p->watchdog_usec);
+                if (r < 0)
+                        return r;
+        }
+
+        if (p->idle_pipe) {
+                _cleanup_free_ char *serialized_fds = NULL;
+
+                for (size_t i = 0; i < 4; ++i) {
+                        int copy = -EBADF;
+
+                        if (p->idle_pipe[i] >= 0) {
+                                copy = fdset_put_dup(fds, p->idle_pipe[i]);
+                                if (copy < 0)
+                                        return copy;
+                        }
+
+                        r = strextendf(&serialized_fds, "%d ", copy);
+                        if (r < 0)
+                                return r;
+                }
+
+                r = serialize_item(f, "exec-parameters-idle-pipe", serialized_fds);
+                if (r < 0)
+                        return r;
+        }
+
+        if (p->stdin_fd >= 0) {
+                r = serialize_fd(f, fds, "exec-parameters-stdin-fd", p->stdin_fd);
+                if (r < 0)
+                        return r;
+        }
+
+        if (p->stdout_fd >= 0) {
+                r = serialize_fd(f, fds, "exec-parameters-stdout-fd", p->stdout_fd);
+                if (r < 0)
+                        return r;
+        }
+
+        if (p->stderr_fd >= 0) {
+                r = serialize_fd(f, fds, "exec-parameters-stderr-fd", p->stderr_fd);
+                if (r < 0)
+                        return r;
+        }
+
+        if (p->exec_fd >= 0) {
+                r = serialize_fd(f, fds, "exec-parameters-exec-fd", p->exec_fd);
+                if (r < 0)
+                        return r;
+        }
+
+        if (p->bpf_outer_map_fd >= 0) {
+                r = serialize_fd(f, fds, "exec-parameters-bpf-outer-map-fd", p->bpf_outer_map_fd);
+                if (r < 0)
+                        return r;
+        }
+
+        r = serialize_item(f, "exec-parameters-notify-socket", p->notify_socket);
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(open_files, file, p->open_files) {
+                _cleanup_free_ char *ofs = NULL;
+
+                r = open_file_to_string(file, &ofs);
+                if (r < 0)
+                        return r;
+
+                r = serialize_item(f, "exec-parameters-open-file", ofs);
+                if (r < 0)
+                        return r;
+        }
+
+        r = serialize_item(f, "exec-parameters-fallback-smack-process-label", p->fallback_smack_process_label);
+        if (r < 0)
+                return r;
+
+        if (p->user_lookup_fd >= 0) {
+                r = serialize_fd(f, fds, "exec-parameters-user-lookup-fd", p->user_lookup_fd);
+                if (r < 0)
+                        return r;
+        }
+
+        r = serialize_strv(f, "exec-parameters-files-env", p->files_env);
+        if (r < 0)
+                return r;
+
+        r = serialize_item(f, "exec-parameters-unit-id", p->unit_id);
+        if (r < 0)
+                return r;
+
+        r = serialize_item(f, "exec-parameters-invocation-id-string", p->invocation_id_string);
+        if (r < 0)
+                return r;
+
+        fputc('\n', f); /* End marker */
+
+        return 0;
+}
+
+static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
+        int r, nr_open;
+
+        assert(p);
+        assert(f);
+        assert(fds);
+
+        nr_open = read_nr_open();
+        if (nr_open < 3)
+                nr_open = HIGH_RLIMIT_NOFILE;
+        assert(nr_open > 0); /* For compilers/static analyzers */
+
+        for (;;) {
+                _cleanup_free_ char *l = NULL;
+                const char *val;
+
+                r = deserialize_read_line(f, &l);
+                if (r < 0)
+                        return r;
+                if (r == 0) /* eof or end marker */
+                        break;
+
+                if ((val = startswith(l, "exec-parameters-runtime-scope="))) {
+                        p->runtime_scope = runtime_scope_from_string(val);
+                        if (p->runtime_scope < 0)
+                                return p->runtime_scope;
+                } else if ((val = startswith(l, "exec-parameters-environment="))) {
+                        r = deserialize_strv(&p->environment, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-n-socket-fds="))) {
+                        if (p->fds)
+                                return -EINVAL; /* Already received */
+
+                        r = safe_atozu(val, &p->n_socket_fds);
+                        if (r < 0)
+                                return r;
+
+                        if (p->n_socket_fds > (size_t) nr_open)
+                                return -EINVAL; /* too many, someone is playing games with us */
+                } else if ((val = startswith(l, "exec-parameters-n-storage-fds="))) {
+                        if (p->fds)
+                                return -EINVAL; /* Already received */
+
+                        r = safe_atozu(val, &p->n_storage_fds);
+                        if (r < 0)
+                                return r;
+
+                        if (p->n_storage_fds > (size_t) nr_open)
+                                return -EINVAL; /* too many, someone is playing games with us */
+                } else if ((val = startswith(l, "exec-parameters-fds="))) {
+                        if (p->n_socket_fds + p->n_storage_fds == 0)
+                                return log_warning_errno(
+                                                SYNTHETIC_ERRNO(EINVAL),
+                                                "Got exec-parameters-fds= without "
+                                                "prior exec-parameters-n-socket-fds= or exec-parameters-n-storage-fds=");
+                        if (p->n_socket_fds + p->n_storage_fds > (size_t) nr_open)
+                                return -EINVAL; /* too many, someone is playing games with us */
+
+                        if (p->fds)
+                                return -EINVAL; /* duplicated */
+
+                        p->fds = new(int, p->n_socket_fds + p->n_storage_fds);
+                        if (!p->fds)
+                                return log_oom_debug();
+
+                        /* Ensure we don't leave any FD uninitialized on error, it makes the fuzzer sad */
+                        for (size_t i = 0; i < p->n_socket_fds + p->n_storage_fds; ++i)
+                                p->fds[i] = -EBADF;
+
+                        for (size_t i = 0; i < p->n_socket_fds + p->n_storage_fds; ++i) {
+                                _cleanup_free_ char *w = NULL;
+                                int fd;
+
+                                r = extract_first_word(&val, &w, WHITESPACE, 0);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        break;
+
+                                if ((fd = parse_fd(w)) < 0 || !fdset_contains(fds, fd))
+                                        log_debug("Failed to parse %s value: %s, ignoring.", l, w);
+                                else {
+                                        r = fdset_remove(fds, fd);
+                                        if (r < 0) {
+                                                log_debug_errno(r, "Failed to remove %s value=%d from fdset, ignoring: %m", l, fd);
+                                                continue;
+                                        }
+
+                                        p->fds[i] = fd;
+                                }
+                        }
+                } else if ((val = startswith(l, "exec-parameters-fd-names="))) {
+                        r = deserialize_strv(&p->fd_names, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-flags="))) {
+                        unsigned flags;
+
+                        r = safe_atou(val, &flags);
+                        if (r < 0)
+                                return r;
+                        p->flags = flags;
+                } else if ((val = startswith(l, "exec-parameters-selinux-context-net="))) {
+                        r = parse_boolean(val);
+                        if (r < 0)
+                                return r;
+
+                        p->selinux_context_net = r;
+                } else if ((val = startswith(l, "exec-parameters-cgroup-supported="))) {
+                        unsigned cgroup_supported;
+
+                        r = safe_atou(val, &cgroup_supported);
+                        if (r < 0)
+                                return r;
+                        p->cgroup_supported = cgroup_supported;
+                } else if ((val = startswith(l, "exec-parameters-cgroup-path="))) {
+                        r = free_and_strdup(&p->cgroup_path, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-cgroup-id="))) {
+                        r = safe_atou64(val, &p->cgroup_id);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-prefix-directories-"))) {
+                        _cleanup_free_ char *type = NULL, *prefix = NULL;
+                        ExecDirectoryType dt;
+
+                        r = extract_many_words(&val, "= ", 0, &type, &prefix, NULL);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                return -EINVAL;
+
+                        dt = exec_directory_type_from_string(type);
+                        if (dt < 0)
+                                return -EINVAL;
+
+                        if (!p->prefix) {
+                                p->prefix = new0(char*, _EXEC_DIRECTORY_TYPE_MAX+1);
+                                if (!p->prefix)
+                                        return log_oom_debug();
+                        }
+
+                        if (isempty(prefix))
+                                p->prefix[dt] = mfree(p->prefix[dt]);
+                        else
+                                free_and_replace(p->prefix[dt], prefix);
+                } else if ((val = startswith(l, "exec-parameters-received-credentials-directory="))) {
+                        r = free_and_strdup(&p->received_credentials_directory, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-received-encrypted-credentials-directory="))) {
+                        r = free_and_strdup(&p->received_encrypted_credentials_directory, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-confirm-spawn="))) {
+                        r = free_and_strdup(&p->confirm_spawn, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-shall-confirm-spawn="))) {
+                        r = parse_boolean(val);
+                        if (r < 0)
+                                return r;
+
+                        p->shall_confirm_spawn = r;
+                } else if ((val = startswith(l, "exec-parameters-watchdog-usec="))) {
+                        r = deserialize_usec(val, &p->watchdog_usec);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-idle-pipe="))) {
+                        if (p->idle_pipe)
+                                return -EINVAL; /* duplicated */
+
+                        p->idle_pipe = new(int, 4);
+                        if (!p->idle_pipe)
+                                return log_oom_debug();
+
+                        p->idle_pipe[0] = p->idle_pipe[1] = p->idle_pipe[2] = p->idle_pipe[3] = -EBADF;
+
+                        for (size_t i = 0; i < 4; ++i) {
+                                _cleanup_free_ char *w = NULL;
+                                int fd;
+
+                                r = extract_first_word(&val, &w, WHITESPACE, 0);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        break;
+
+                                if ((fd = parse_fd(w)) < 0 || !fdset_contains(fds, fd))
+                                        log_debug("Failed to parse %s value: %s, ignoring.", l, w);
+                                else {
+                                        r = fdset_remove(fds, fd);
+                                        if (r < 0) {
+                                                log_debug_errno(r, "Failed to remove %s value=%d from fdset, ignoring: %m", l, fd);
+                                                continue;
+                                        }
+
+                                        p->idle_pipe[i] = fd;
+                                }
+                        }
+                } else if ((val = startswith(l, "exec-parameters-stdin-fd="))) {
+                        int fd;
+
+                        if ((fd = parse_fd(val)) < 0 || !fdset_contains(fds, fd))
+                                log_debug("Failed to parse %s value: %s, ignoring.", l, val);
+                        else {
+                                r = fdset_remove(fds, fd);
+                                if (r < 0) {
+                                        log_debug_errno(r, "Failed to remove %s value=%d from fdset, ignoring: %m", l, fd);
+                                        continue;
+                                }
+
+                                p->stdin_fd = fd;
+                        }
+                } else if ((val = startswith(l, "exec-parameters-stdout-fd="))) {
+                        int fd;
+
+                        if ((fd = parse_fd(val)) < 0 || !fdset_contains(fds, fd))
+                                log_debug("Failed to parse %s value: %s, ignoring.", l, val);
+                        else {
+                                r = fdset_remove(fds, fd);
+                                if (r < 0) {
+                                        log_debug_errno(r, "Failed to remove %s value=%d from fdset, ignoring: %m", l, fd);
+                                        continue;
+                                }
+
+                                p->stdout_fd = fd;
+                        }
+                } else if ((val = startswith(l, "exec-parameters-stderr-fd="))) {
+                        int fd;
+
+                        if ((fd = parse_fd(val)) < 0 || !fdset_contains(fds, fd))
+                                log_debug("Failed to parse %s value: %s, ignoring.", l, val);
+                        else {
+                                r = fdset_remove(fds, fd);
+                                if (r < 0) {
+                                        log_debug_errno(r, "Failed to remove %s value=%d from fdset, ignoring: %m", l, fd);
+                                        continue;
+                                }
+
+                                p->stderr_fd = fd;
+                        }
+                } else if ((val = startswith(l, "exec-parameters-exec-fd="))) {
+                        int fd;
+
+                        if ((fd = parse_fd(val)) < 0 || !fdset_contains(fds, fd))
+                                log_debug("Failed to parse %s value: %s, ignoring.", l, val);
+                        else {
+                                r = fdset_remove(fds, fd);
+                                if (r < 0) {
+                                        log_debug_errno(r, "Failed to remove %s value=%d from fdset, ignoring: %m", l, fd);
+                                        continue;
+                                }
+
+                                /* This is special and relies on close-on-exec semantics, make sure it's
+                                 * there */
+                                r = fd_cloexec(fd, true);
+                                if (r < 0)
+                                        return r;
+
+                                p->exec_fd = fd;
+                        }
+                } else if ((val = startswith(l, "exec-parameters-bpf-outer-map-fd="))) {
+                        int fd;
+
+                        if ((fd = parse_fd(val)) < 0 || !fdset_contains(fds, fd))
+                                log_debug("Failed to parse %s value: %s, ignoring.", l, val);
+                        else {
+                                r = fdset_remove(fds, fd);
+                                if (r < 0) {
+                                        log_debug_errno(r, "Failed to remove %s value=%d from fdset, ignoring: %m", l, fd);
+                                        continue;
+                                }
+
+                                p->bpf_outer_map_fd = fd;
+                        }
+                } else if ((val = startswith(l, "exec-parameters-notify-socket="))) {
+                        r = free_and_strdup(&p->notify_socket, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-open-file="))) {
+                        OpenFile *of = NULL;
+
+                        r = open_file_parse(val, &of);
+                        if (r < 0)
+                                return r;
+
+                        LIST_APPEND(open_files, p->open_files, of);
+                } else if ((val = startswith(l, "exec-parameters-fallback-smack-process-label="))) {
+                        r = free_and_strdup(&p->fallback_smack_process_label, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-user-lookup-fd="))) {
+                        int fd;
+
+                        if ((fd = parse_fd(val)) < 0 || !fdset_contains(fds, fd))
+                                log_debug("Failed to parse %s value: %s, ignoring.", l, val);
+                        else {
+                                r = fdset_remove(fds, fd);
+                                if (r < 0) {
+                                        log_debug_errno(r, "Failed to remove %s value=%d from fdset, ignoring: %m", l, fd);
+                                        continue;
+                                }
+
+                                p->user_lookup_fd = fd;
+                        }
+                } else if ((val = startswith(l, "exec-parameters-files-env="))) {
+                        r = deserialize_strv(&p->files_env, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-unit-id="))) {
+                        r = free_and_strdup(&p->unit_id, val);
+                        if (r < 0)
+                                return r;
+                } else if ((val = startswith(l, "exec-parameters-invocation-id-string="))) {
+                        if (strlen(val) > SD_ID128_STRING_MAX - 1)
+                                return -EINVAL;
+
+                        r = sd_id128_from_string(val, &p->invocation_id);
+                        if (r < 0)
+                                return r;
+
+                        sd_id128_to_string(p->invocation_id, p->invocation_id_string);
+                } else
+                        log_warning("Failed to parse serialized line, ignorning: %s", l);
+        }
+
+        /* Bail out if we got exec-parameters-n-{socket/storage}-fds= but no corresponding
+         * exec-parameters-fds= */
+        if (p->n_socket_fds + p->n_storage_fds > 0 && !p->fds)
+                return -EINVAL;
+
+        return 0;
+}
+
 static int serialize_std_out_err(const ExecContext *c, FILE *f, int fileno) {
         char *key, *value;
         const char *type;
@@ -2169,7 +2719,8 @@ int exec_serialize_invocation(
                 FILE *f,
                 FDSet *fds,
                 const ExecContext *ctx,
-                const ExecCommand *cmd) {
+                const ExecCommand *cmd,
+                const ExecParameters *p) {
 
         int r;
 
@@ -2184,6 +2735,10 @@ int exec_serialize_invocation(
         if (r < 0)
                 return log_debug_errno(r, "Failed to serialize command: %m");
 
+        r = exec_parameters_serialize(p, f, fds);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to serialize parameters: %m");
+
         return 0;
 }
 
@@ -2191,7 +2746,8 @@ int exec_deserialize_invocation(
                 FILE *f,
                 FDSet *fds,
                 ExecContext *ctx,
-                ExecCommand *cmd) {
+                ExecCommand *cmd,
+                ExecParameters *p) {
 
         int r;
 
@@ -2206,5 +2762,9 @@ int exec_deserialize_invocation(
         if (r < 0)
                 return log_debug_errno(r, "Failed to deserialize command: %m");
 
+        r = exec_parameters_deserialize(p, f, fds);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to deserialize parameters: %m");
+
         return 0;
 }
index 339ba8cafa6d92cb96b3b13d4dcf316c6596cc9d..9cd908db80562c8b5e3dea98261f776ce28ac7ba 100644 (file)
@@ -9,9 +9,11 @@
 int exec_serialize_invocation(FILE *f,
         FDSet *fds,
         const ExecContext *ctx,
-        const ExecCommand *cmd);
+        const ExecCommand *cmd,
+        const ExecParameters *p);
 
 int exec_deserialize_invocation(FILE *f,
         FDSet *fds,
         ExecContext *ctx,
-        ExecCommand *cmd);
+        ExecCommand *cmd,
+        ExecParameters *p);
index bcd4a39274dff7c997f7f76d40a6038f13593ec6..25f8531d44a67f151426e277a35ade74032958c1 100644 (file)
@@ -420,14 +420,14 @@ struct ExecParameters {
         bool selinux_context_net:1;
 
         CGroupMask cgroup_supported;
-        const char *cgroup_path;
+        char *cgroup_path;
         uint64_t cgroup_id;
 
         char **prefix;
-        const char *received_credentials_directory;
-        const char *received_encrypted_credentials_directory;
+        char *received_credentials_directory;
+        char *received_encrypted_credentials_directory;
 
-        const char *confirm_spawn;
+        char *confirm_spawn;
         bool shall_confirm_spawn;
 
         usec_t watchdog_usec;
@@ -441,11 +441,11 @@ struct ExecParameters {
         /* An fd that is closed by the execve(), and thus will result in EOF when the execve() is done */
         int exec_fd;
 
-        const char *notify_socket;
+        char *notify_socket;
 
         LIST_HEAD(OpenFile, open_files);
 
-        const char *fallback_smack_process_label;
+        char *fallback_smack_process_label;
 
         char **files_env;
         int user_lookup_fd;
index cd4282a26b799d4e3afb2095a93dbd1a35d4ba5d..b71c21580ea27d304f8b932cfea6b7ce4a18f72e 100644 (file)
@@ -5369,7 +5369,7 @@ int unit_set_exec_params(Unit *u, ExecParameters *p) {
 
         p->runtime_scope = u->manager->runtime_scope;
 
-        p->confirm_spawn = manager_get_confirm_spawn(u->manager);
+        p->confirm_spawn = (char *)manager_get_confirm_spawn(u->manager);
         p->cgroup_supported = u->manager->cgroup_supported;
         p->prefix = u->manager->prefix;
         SET_FLAG(p->flags, EXEC_PASS_LOG_UNIT|EXEC_CHOWN_DIRECTORIES, MANAGER_IS_SYSTEM(u->manager));