From b396116e0131ce093fddde72e498c822b7ca85fa Mon Sep 17 00:00:00 2001 From: Linux_zhang Date: Fri, 8 Aug 2025 15:39:46 +0800 Subject: [PATCH] sync patches from systemd community --- ...ec-credential-add-missing-assertions.patch | 113 +++++ ...tial-use-FOREACH_ARRAY-at-one-more-p.patch | 74 +++ ...troduce-exec_params_need_credentials.patch | 127 +++++ ...ntial-dir-across-start-and-start-pos.patch | 459 ++++++++++++++++++ ...ow-ExecStartPost-cmds-to-access-cred.patch | 27 ++ ...-t-setup-credentials-for-ExecConditi.patch | 34 ++ ...service-introduce-service_exec_flags.patch | 268 ++++++++++ systemd.spec | 13 +- 8 files changed, 1114 insertions(+), 1 deletion(-) create mode 100644 backport-core-exec-credential-add-missing-assertions.patch create mode 100644 backport-core-exec-credential-use-FOREACH_ARRAY-at-one-more-p.patch create mode 100644 backport-core-introduce-exec_params_need_credentials.patch create mode 100644 backport-core-reuse-credential-dir-across-start-and-start-pos.patch create mode 100644 backport-core-service-allow-ExecStartPost-cmds-to-access-cred.patch create mode 100644 backport-core-service-don-t-setup-credentials-for-ExecConditi.patch create mode 100644 backport-core-service-introduce-service_exec_flags.patch diff --git a/backport-core-exec-credential-add-missing-assertions.patch b/backport-core-exec-credential-add-missing-assertions.patch new file mode 100644 index 0000000..61e404d --- /dev/null +++ b/backport-core-exec-credential-add-missing-assertions.patch @@ -0,0 +1,113 @@ +From 3a0f6c217d178ff97c0fb7182604f852569be580 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Tue, 6 Feb 2024 22:17:34 +0800 +Subject: [PATCH] core/exec-credential: add missing assertions + +--- + src/core/exec-credential.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c +index 6bcfb68..c59018e 100644 +--- a/src/core/exec-credential.c ++++ b/src/core/exec-credential.c +@@ -172,6 +172,10 @@ static int write_credential( + _cleanup_close_ int fd = -EBADF; + int r; + ++ assert(dfd >= 0); ++ assert(id); ++ assert(data || size == 0); ++ + r = tempfn_random_child("", "cred", &tmp); + if (r < 0) + return r; +@@ -224,7 +228,6 @@ typedef enum CredentialSearchPath { + } CredentialSearchPath; + + static char **credential_search_path(const ExecParameters *params, CredentialSearchPath path) { +- + _cleanup_strv_free_ char **l = NULL; + + assert(params); +@@ -275,6 +278,10 @@ static int maybe_decrypt_and_write_credential( + size_t add; + int r; + ++ assert(dir_fd >= 0); ++ assert(id); ++ assert(left); ++ + if (encrypted) { + size_t plaintext_size = 0; + +@@ -302,7 +309,7 @@ static int maybe_decrypt_and_write_credential( + static int load_credential_glob( + const char *path, + bool encrypted, +- char **search_path, ++ char * const *search_path, + ReadFullFileFlags flags, + int write_dfd, + uid_t uid, +@@ -312,6 +319,11 @@ static int load_credential_glob( + + int r; + ++ assert(path); ++ assert(search_path); ++ assert(write_dfd >= 0); ++ assert(left); ++ + STRV_FOREACH(d, search_path) { + _cleanup_globfree_ glob_t pglob = {}; + _cleanup_free_ char *j = NULL; +@@ -518,6 +530,9 @@ static int load_cred_recurse_dir_cb( + _cleanup_free_ char *sub_id = NULL; + int r; + ++ assert(path); ++ assert(de); ++ + if (event != RECURSE_DIR_ENTRY) + return RECURSE_DIR_CONTINUE; + +@@ -574,6 +589,8 @@ static int acquire_credentials( + int r; + + assert(context); ++ assert(params); ++ assert(unit); + assert(p); + + dfd = open(p, O_DIRECTORY|O_CLOEXEC); +@@ -618,8 +635,7 @@ static int acquire_credentials( + &left); + else + /* Directory */ +- r = recurse_dir( +- sub_fd, ++ r = recurse_dir(sub_fd, + /* path= */ lc->id, /* recurse_dir() will suffix the subdir paths from here to the top-level id */ + /* statx_mask= */ 0, + /* n_depth_max= */ UINT_MAX, +@@ -760,6 +776,8 @@ static int setup_credentials_internal( + const char *where; + + assert(context); ++ assert(params); ++ assert(unit); + assert(final); + assert(workspace); + +@@ -905,6 +923,7 @@ int exec_setup_credentials( + + assert(context); + assert(params); ++ assert(unit); + + if (!exec_context_has_credentials(context)) + return 0; +-- +2.43.0 + diff --git a/backport-core-exec-credential-use-FOREACH_ARRAY-at-one-more-p.patch b/backport-core-exec-credential-use-FOREACH_ARRAY-at-one-more-p.patch new file mode 100644 index 0000000..3b201f6 --- /dev/null +++ b/backport-core-exec-credential-use-FOREACH_ARRAY-at-one-more-p.patch @@ -0,0 +1,74 @@ +From 0f781376c033c8c8d38157a810e45cf226bc8d72 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Tue, 6 Feb 2024 22:20:49 +0800 +Subject: [PATCH] core/exec-credential: use FOREACH_ARRAY at one more place + +--- + src/core/exec-credential.c | 40 ++++++++++++++++++-------------------- + 1 file changed, 19 insertions(+), 21 deletions(-) + +diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c +index 3b017972a7..7248ad0348 100644 +--- a/src/core/exec-credential.c ++++ b/src/core/exec-credential.c +@@ -342,38 +342,36 @@ static int load_credential_glob( + if (r < 0) + return r; + +- for (size_t n = 0; n < pglob.gl_pathc; n++) { ++ FOREACH_ARRAY(p, pglob.gl_pathv, pglob.gl_pathc) { + _cleanup_free_ char *fn = NULL; + _cleanup_(erase_and_freep) char *data = NULL; + size_t size; + + /* path is absolute, hence pass AT_FDCWD as nop dir fd here */ + r = read_full_file_full( +- AT_FDCWD, +- pglob.gl_pathv[n], +- UINT64_MAX, +- encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX, +- flags, +- NULL, +- &data, &size); ++ AT_FDCWD, ++ *p, ++ UINT64_MAX, ++ encrypted ? CREDENTIAL_ENCRYPTED_SIZE_MAX : CREDENTIAL_SIZE_MAX, ++ flags, ++ NULL, ++ &data, &size); + if (r < 0) +- return log_debug_errno(r, "Failed to read credential '%s': %m", +- pglob.gl_pathv[n]); ++ return log_debug_errno(r, "Failed to read credential '%s': %m", *p); + +- r = path_extract_filename(pglob.gl_pathv[n], &fn); ++ r = path_extract_filename(*p, &fn); + if (r < 0) +- return log_debug_errno(r, "Failed to extract filename from '%s': %m", +- pglob.gl_pathv[n]); ++ return log_debug_errno(r, "Failed to extract filename from '%s': %m", *p); + + r = maybe_decrypt_and_write_credential( +- write_dfd, +- fn, +- encrypted, +- uid, +- gid, +- ownership_ok, +- data, size, +- left); ++ write_dfd, ++ fn, ++ encrypted, ++ uid, ++ gid, ++ ownership_ok, ++ data, size, ++ left); + if (r == -EEXIST) + continue; + if (r < 0) +-- +2.43.0 + diff --git a/backport-core-introduce-exec_params_need_credentials.patch b/backport-core-introduce-exec_params_need_credentials.patch new file mode 100644 index 0000000..d873f71 --- /dev/null +++ b/backport-core-introduce-exec_params_need_credentials.patch @@ -0,0 +1,127 @@ +From 1221ba0f6f2438035a601ef55cb651bb030456f1 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Tue, 6 Feb 2024 21:53:35 +0800 +Subject: [PATCH] core: introduce exec_params_need_credentials + +Also rename EXEC_WRITE_CREDENTIALS to EXEC_SETUP_CREDENTIALS. +--- + src/core/exec-credential.c | 10 ++++++++-- + src/core/exec-credential.h | 2 ++ + src/core/exec-invoke.c | 18 +++++++----------- + src/core/execute.h | 2 +- + src/core/service.c | 2 +- + 5 files changed, 19 insertions(+), 15 deletions(-) + +diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c +index cd877f0..78bb75d 100644 +--- a/src/core/exec-credential.c ++++ b/src/core/exec-credential.c +@@ -48,6 +48,12 @@ DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + char, string_hash_func, string_compare_func, + ExecLoadCredential, exec_load_credential_free); + ++bool exec_params_need_credentials(const ExecParameters *p) { ++ assert(p); ++ ++ return FLAGS_SET(p->flags, EXEC_SETUP_CREDENTIALS); ++} ++ + bool exec_context_has_credentials(const ExecContext *c) { + assert(c); + +@@ -106,7 +112,7 @@ int exec_context_get_credential_directory( + assert(unit); + assert(ret); + +- if (!exec_context_has_credentials(context)) { ++ if (!exec_params_need_credentials(params) || !exec_context_has_credentials(context)) { + *ret = NULL; + return 0; + } +@@ -923,7 +929,7 @@ int exec_setup_credentials( + assert(params); + assert(unit); + +- if (!exec_context_has_credentials(context)) ++ if (!exec_params_need_credentials(params) || !exec_context_has_credentials(context)) + return 0; + + if (!params->prefix[EXEC_DIRECTORY_RUNTIME]) +diff --git a/src/core/exec-credential.h b/src/core/exec-credential.h +index 6f836fb..3a9f5d7 100644 +--- a/src/core/exec-credential.h ++++ b/src/core/exec-credential.h +@@ -34,6 +34,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(ExecLoadCredential*, exec_load_credential_free); + extern const struct hash_ops exec_set_credential_hash_ops; + extern const struct hash_ops exec_load_credential_hash_ops; + ++bool exec_params_need_credentials(const ExecParameters *p); ++ + bool exec_context_has_encrypted_credentials(ExecContext *c); + bool exec_context_has_credentials(const ExecContext *c); + +diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c +index b0f58a1..05a60ae 100644 +--- a/src/core/exec-invoke.c ++++ b/src/core/exec-invoke.c +@@ -3076,11 +3076,9 @@ static int apply_mount_namespace( + params, + "shared mount propagation hidden by other fs namespacing unit settings: ignoring"); + +- if (FLAGS_SET(params->flags, EXEC_WRITE_CREDENTIALS)) { +- r = exec_context_get_credential_directory(context, params, params->unit_id, &creds_path); +- if (r < 0) +- return r; +- } ++ r = exec_context_get_credential_directory(context, params, params->unit_id, &creds_path); ++ if (r < 0) ++ return r; + + if (params->runtime_scope == RUNTIME_SCOPE_SYSTEM) { + propagate_dir = path_join("/run/systemd/propagate/", params->unit_id); +@@ -4463,12 +4461,10 @@ int exec_invoke( + return log_exec_error_errno(context, params, r, "Failed to set up special execution directory in %s: %m", params->prefix[dt]); + } + +- if (FLAGS_SET(params->flags, EXEC_WRITE_CREDENTIALS)) { +- r = exec_setup_credentials(context, params, params->unit_id, uid, gid); +- if (r < 0) { +- *exit_status = EXIT_CREDENTIALS; +- return log_exec_error_errno(context, params, r, "Failed to set up credentials: %m"); +- } ++ r = exec_setup_credentials(context, params, params->unit_id, uid, gid); ++ if (r < 0) { ++ *exit_status = EXIT_CREDENTIALS; ++ return log_exec_error_errno(context, params, r, "Failed to set up credentials: %m"); + } + + r = build_environment( +diff --git a/src/core/execute.h b/src/core/execute.h +index 5a6927a..f3ae08c 100644 +--- a/src/core/execute.h ++++ b/src/core/execute.h +@@ -399,7 +399,7 @@ typedef enum ExecFlags { + EXEC_CGROUP_DELEGATE = 1 << 6, + EXEC_IS_CONTROL = 1 << 7, + EXEC_CONTROL_CGROUP = 1 << 8, /* Place the process not in the indicated cgroup but in a subcgroup '/.control', but only EXEC_CGROUP_DELEGATE and EXEC_IS_CONTROL is set, too */ +- EXEC_WRITE_CREDENTIALS = 1 << 9, /* Set up the credential store logic */ ++ EXEC_SETUP_CREDENTIALS = 1 << 9, /* Set up the credential store logic */ + + /* The following are not used by execute.c, but by consumers internally */ + EXEC_PASS_FDS = 1 << 10, +diff --git a/src/core/service.c b/src/core/service.c +index bd27acb..abc3343 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -1618,7 +1618,7 @@ static ExecFlags service_exec_flags(ServiceExecCommand command_id) { + + /* All start phases get access to credentials */ + if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START, SERVICE_EXEC_START_POST)) +- flags |= EXEC_WRITE_CREDENTIALS; ++ flags |= EXEC_SETUP_CREDENTIALS; + + if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START)) + flags |= EXEC_SETENV_MONITOR_RESULT; +-- +2.43.0 + diff --git a/backport-core-reuse-credential-dir-across-start-and-start-pos.patch b/backport-core-reuse-credential-dir-across-start-and-start-pos.patch new file mode 100644 index 0000000..457bb7a --- /dev/null +++ b/backport-core-reuse-credential-dir-across-start-and-start-pos.patch @@ -0,0 +1,459 @@ +From cfbf7538d87023840c5574fa5b0452e5b0f42149 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sun, 4 Feb 2024 23:22:46 +0800 +Subject: [PATCH] core: reuse credential dir across start and start-post if + populated, fresh otherwise + +Currently, exec_setup_credential() always rewrite all credentials +upon exec_invoke(), i.e. invocation of each ExecCommand, and within +a single tmpfs instance. This is problematic though: + +* When writing each tmp cred file, we essentially double the size + of the credential. Therefore, if one cred is bigger than half + of CREDENTIALS_TOTAL_SIZE_MAX, confusing ENOSPC occurs (see also + https://github.com/systemd/systemd/pull/24734#issuecomment-1925440546) + +* Credential is a unit-wide thing and thus should not change + during the whole lifetime of main process. However, if e.g. + a on-disk credential or SetCredential= in unit file + changes between ExecStart= and ExecStartPost=, + the credentials are overwritten when the latter gets to run, + and the already-running main process is suddenly seeing + completely different creds. + +So, let's try to reuse final cred dir if the main process has started +and the tmpfs has been populated, so that the creds used is stable +across all ExecStart= and ExecStartPost=-s. We still want to retain +the ability of updating creds through ExecStartPre= though, therefore +we forcibly use a fresh cred dir for those. 'Fresh' means to actually +unmount the old tmpfs first, so the first problem goes away, too. +--- + src/core/exec-credential.c | 119 +++++++++++++++++++------------------ + src/core/execute.h | 29 ++++----- + src/core/service.c | 37 +++++++----- + test/units/testsuite-54.sh | 25 ++++++++ + 4 files changed, 121 insertions(+), 89 deletions(-) + +diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c +index 78bb75d..50c2c13 100644 +--- a/src/core/exec-credential.c ++++ b/src/core/exec-credential.c +@@ -51,7 +51,7 @@ DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + bool exec_params_need_credentials(const ExecParameters *p) { + assert(p); + +- return FLAGS_SET(p->flags, EXEC_SETUP_CREDENTIALS); ++ return p->flags & (EXEC_SETUP_CREDENTIALS|EXEC_SETUP_CREDENTIALS_FRESH); + } + + bool exec_context_has_credentials(const ExecContext *c) { +@@ -774,10 +774,9 @@ static int setup_credentials_internal( + uid_t uid, + gid_t gid) { + ++ bool final_mounted; + int r, workspace_mounted; /* negative if we don't know yet whether we have/can mount something; true + * if we mounted something; false if we definitely can't mount anything */ +- bool final_mounted; +- const char *where; + + assert(context); + assert(params); +@@ -785,6 +784,30 @@ static int setup_credentials_internal( + assert(final); + assert(workspace); + ++ r = path_is_mount_point(final, NULL, 0); ++ if (r < 0) ++ return r; ++ final_mounted = r > 0; ++ ++ if (final_mounted) { ++ if (FLAGS_SET(params->flags, EXEC_SETUP_CREDENTIALS_FRESH)) { ++ r = umount_verbose(LOG_DEBUG, final, MNT_DETACH|UMOUNT_NOFOLLOW); ++ if (r < 0) ++ return r; ++ ++ final_mounted = false; ++ } else { ++ /* We can reuse the previous credential dir */ ++ r = dir_is_empty(final, /* ignore_hidden_or_backup = */ false); ++ if (r < 0) ++ return r; ++ if (r == 0) { ++ log_debug("Credential dir for unit '%s' already set up, skipping.", unit); ++ return 0; ++ } ++ } ++ } ++ + if (reuse_workspace) { + r = path_is_mount_point(workspace, NULL, 0); + if (r < 0) +@@ -797,40 +820,19 @@ static int setup_credentials_internal( + } else + workspace_mounted = -1; /* ditto */ + +- r = path_is_mount_point(final, NULL, 0); +- if (r < 0) +- return r; +- if (r > 0) { +- /* If the final place already has something mounted, we use that. If the workspace also has +- * something mounted we assume it's actually the same mount (but with MS_RDONLY +- * different). */ +- final_mounted = true; +- +- if (workspace_mounted < 0) { +- /* If the final place is mounted, but the workspace isn't, then let's bind mount +- * the final version to the workspace, and make it writable, so that we can make +- * changes */ +- +- r = mount_nofollow_verbose(LOG_DEBUG, final, workspace, NULL, MS_BIND|MS_REC, NULL); +- if (r < 0) +- return r; +- +- r = mount_nofollow_verbose(LOG_DEBUG, NULL, workspace, NULL, MS_BIND|MS_REMOUNT|credentials_fs_mount_flags(/* ro= */ false), NULL); +- if (r < 0) +- return r; +- +- workspace_mounted = true; +- } +- } else +- final_mounted = false; ++ /* If both the final place and the workspace are mounted, we have no mounts to set up, based on ++ * the assumption that they're actually the same tmpfs (but the latter with MS_RDONLY different). ++ * If the workspace is not mounted, we just bind the final place over and make it writable. */ ++ must_mount = must_mount || final_mounted; + + if (workspace_mounted < 0) { +- /* Nothing is mounted on the workspace yet, let's try to mount something now */ +- +- r = mount_credentials_fs(workspace, CREDENTIALS_TOTAL_SIZE_MAX, /* ro= */ false); +- if (r < 0) { +- /* If that didn't work, try to make a bind mount from the final to the workspace, so +- * that we can make it writable there. */ ++ if (!final_mounted) ++ /* Nothing is mounted on the workspace yet, let's try to mount a new tmpfs if ++ * not using the final place. */ ++ r = mount_credentials_fs(workspace, CREDENTIALS_TOTAL_SIZE_MAX, /* ro= */ false); ++ if (final_mounted || r < 0) { ++ /* If using final place or failed to mount new tmpfs, make a bind mount from ++ * the final to the workspace, so that we can make it writable there. */ + r = mount_nofollow_verbose(LOG_DEBUG, final, workspace, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) { + if (!ERRNO_IS_PRIVILEGE(r)) +@@ -843,12 +845,19 @@ static int setup_credentials_internal( + return r; + + /* If we lack privileges to bind mount stuff, then let's gracefully proceed +- * for compat with container envs, and just use the final dir as is. */ ++ * for compat with container envs, and just use the final dir as is. ++ * Final place must not be mounted in this case (refused by must_mount ++ * above) */ + + workspace_mounted = false; + } else { + /* Make the new bind mount writable (i.e. drop MS_RDONLY) */ +- r = mount_nofollow_verbose(LOG_DEBUG, NULL, workspace, NULL, MS_BIND|MS_REMOUNT|credentials_fs_mount_flags(/* ro= */ false), NULL); ++ r = mount_nofollow_verbose(LOG_DEBUG, ++ NULL, ++ workspace, ++ NULL, ++ MS_BIND|MS_REMOUNT|credentials_fs_mount_flags(/* ro= */ false), ++ NULL); + if (r < 0) + return r; + +@@ -858,34 +867,26 @@ static int setup_credentials_internal( + workspace_mounted = true; + } + +- assert(!must_mount || workspace_mounted > 0); +- where = workspace_mounted ? workspace : final; ++ assert(workspace_mounted >= 0); ++ assert(!must_mount || workspace_mounted); ++ ++ const char *where = workspace_mounted ? workspace : final; + + (void) label_fix_full(AT_FDCWD, where, final, 0); + + r = acquire_credentials(context, params, unit, where, uid, gid, workspace_mounted); +- if (r < 0) +- return r; +- +- if (workspace_mounted) { +- bool install; +- +- /* Determine if we should actually install the prepared mount in the final location by bind +- * mounting it there. We do so only if the mount is not established there already, and if the +- * mount is actually non-empty (i.e. carries at least one credential). Not that in the best +- * case we are doing all this in a mount namespace, thus no one else will see that we +- * allocated a file system we are getting rid of again here. */ ++ if (r < 0) { ++ /* If we're using final place as workspace, and failed to acquire credentials, we might ++ * have left half-written creds there. Let's get rid of the whole mount, so future ++ * calls won't reuse it. */ + if (final_mounted) +- install = false; /* already installed */ +- else { +- r = dir_is_empty(where, /* ignore_hidden_or_backup= */ false); +- if (r < 0) +- return r; ++ (void) umount_verbose(LOG_DEBUG, final, MNT_DETACH|UMOUNT_NOFOLLOW); + +- install = r == 0; /* install only if non-empty */ +- } ++ return r; ++ } + +- if (install) { ++ if (workspace_mounted) { ++ if (!final_mounted) { + /* Make workspace read-only now, so that any bind mount we make from it defaults to + * read-only too */ + r = mount_nofollow_verbose(LOG_DEBUG, NULL, workspace, NULL, MS_BIND|MS_REMOUNT|credentials_fs_mount_flags(/* ro= */ true), NULL); +@@ -895,7 +896,7 @@ static int setup_credentials_internal( + /* And mount it to the final place, read-only */ + r = mount_nofollow_verbose(LOG_DEBUG, workspace, final, NULL, MS_MOVE, NULL); + } else +- /* Otherwise get rid of it */ ++ /* Otherwise we just get rid of the bind mount of final place */ + r = umount_verbose(LOG_DEBUG, workspace, MNT_DETACH|UMOUNT_NOFOLLOW); + if (r < 0) + return r; +diff --git a/src/core/execute.h b/src/core/execute.h +index f3ae08c..b9de527 100644 +--- a/src/core/execute.h ++++ b/src/core/execute.h +@@ -390,22 +390,23 @@ static inline bool exec_context_with_rootfs(const ExecContext *c) { + } + + typedef enum ExecFlags { +- EXEC_APPLY_SANDBOXING = 1 << 0, +- EXEC_APPLY_CHROOT = 1 << 1, +- EXEC_APPLY_TTY_STDIN = 1 << 2, +- EXEC_PASS_LOG_UNIT = 1 << 3, /* Whether to pass the unit name to the service's journal stream connection */ +- EXEC_CHOWN_DIRECTORIES = 1 << 4, /* chown() the runtime/state/cache/log directories to the user we run as, under all conditions */ +- EXEC_NSS_DYNAMIC_BYPASS = 1 << 5, /* Set the SYSTEMD_NSS_DYNAMIC_BYPASS environment variable, to disable nss-systemd blocking on PID 1, for use by dbus-daemon */ +- EXEC_CGROUP_DELEGATE = 1 << 6, +- EXEC_IS_CONTROL = 1 << 7, +- EXEC_CONTROL_CGROUP = 1 << 8, /* Place the process not in the indicated cgroup but in a subcgroup '/.control', but only EXEC_CGROUP_DELEGATE and EXEC_IS_CONTROL is set, too */ +- EXEC_SETUP_CREDENTIALS = 1 << 9, /* Set up the credential store logic */ ++ EXEC_APPLY_SANDBOXING = 1 << 0, ++ EXEC_APPLY_CHROOT = 1 << 1, ++ EXEC_APPLY_TTY_STDIN = 1 << 2, ++ EXEC_PASS_LOG_UNIT = 1 << 3, /* Whether to pass the unit name to the service's journal stream connection */ ++ EXEC_CHOWN_DIRECTORIES = 1 << 4, /* chown() the runtime/state/cache/log directories to the user we run as, under all conditions */ ++ EXEC_NSS_DYNAMIC_BYPASS = 1 << 5, /* Set the SYSTEMD_NSS_DYNAMIC_BYPASS environment variable, to disable nss-systemd blocking on PID 1, for use by dbus-daemon */ ++ EXEC_CGROUP_DELEGATE = 1 << 6, ++ EXEC_IS_CONTROL = 1 << 7, ++ EXEC_CONTROL_CGROUP = 1 << 8, /* Place the process not in the indicated cgroup but in a subcgroup '/.control', but only EXEC_CGROUP_DELEGATE and EXEC_IS_CONTROL is set, too */ ++ EXEC_SETUP_CREDENTIALS = 1 << 9, /* Set up the credential store logic */ ++ EXEC_SETUP_CREDENTIALS_FRESH = 1 << 10, /* Set up a new credential store (disable reuse) */ + + /* The following are not used by execute.c, but by consumers internally */ +- EXEC_PASS_FDS = 1 << 10, +- EXEC_SETENV_RESULT = 1 << 11, +- EXEC_SET_WATCHDOG = 1 << 12, +- EXEC_SETENV_MONITOR_RESULT = 1 << 13, /* Pass exit status to OnFailure= and OnSuccess= dependencies. */ ++ EXEC_PASS_FDS = 1 << 11, ++ EXEC_SETENV_RESULT = 1 << 12, ++ EXEC_SET_WATCHDOG = 1 << 13, ++ EXEC_SETENV_MONITOR_RESULT = 1 << 14, /* Pass exit status to OnFailure= and OnSuccess= dependencies. */ + } ExecFlags; + + /* Parameters for a specific invocation of a command. This structure is put together right before a command is +diff --git a/src/core/service.c b/src/core/service.c +index abc3343..a1ff3a3 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -1604,27 +1604,33 @@ static Service *service_get_triggering_service(Service *s) { + return NULL; + } + +-static ExecFlags service_exec_flags(ServiceExecCommand command_id) { ++static ExecFlags service_exec_flags(ServiceExecCommand command_id, ExecFlags cred_flag) { + /* All service main/control processes honor sandboxing and namespacing options (except those + explicitly excluded in service_spawn()) */ + ExecFlags flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT; + + assert(command_id >= 0); + assert(command_id < _SERVICE_EXEC_COMMAND_MAX); ++ assert((cred_flag & ~(EXEC_SETUP_CREDENTIALS_FRESH|EXEC_SETUP_CREDENTIALS)) == 0); ++ assert((cred_flag != 0) == (command_id == SERVICE_EXEC_START)); + + /* Control processes spawned before main process also get tty access */ + if (IN_SET(command_id, SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START, /* FIXME */ SERVICE_EXEC_STOP_POST)) + flags |= EXEC_APPLY_TTY_STDIN; + +- /* All start phases get access to credentials */ +- if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START, SERVICE_EXEC_START_POST)) ++ /* All start phases get access to credentials. ExecStartPre= gets a new credential store upon ++ * every invocation, so that updating credential files through it works. When the first main process ++ * starts, passed creds become stable. Also see 'cred_flag'. */ ++ if (command_id == SERVICE_EXEC_START_PRE) ++ flags |= EXEC_SETUP_CREDENTIALS_FRESH; ++ if (command_id == SERVICE_EXEC_START_POST) + flags |= EXEC_SETUP_CREDENTIALS; + + if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START)) + flags |= EXEC_SETENV_MONITOR_RESULT; + + if (command_id == SERVICE_EXEC_START) +- return flags|EXEC_PASS_FDS|EXEC_SET_WATCHDOG; ++ return flags|cred_flag|EXEC_PASS_FDS|EXEC_SET_WATCHDOG; + + flags |= EXEC_IS_CONTROL; + +@@ -1641,13 +1647,12 @@ static ExecFlags service_exec_flags(ServiceExecCommand command_id) { + static int service_spawn_internal( + const char *caller, + Service *s, +- ServiceExecCommand command_id, + ExecCommand *c, ++ ExecFlags flags, + usec_t timeout, + PidRef *ret_pid) { + +- _cleanup_(exec_params_shallow_clear) ExecParameters exec_params = +- EXEC_PARAMETERS_INIT(service_exec_flags(command_id)); ++ _cleanup_(exec_params_shallow_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(flags); + _cleanup_(sd_event_source_unrefp) sd_event_source *exec_fd_source = NULL; + _cleanup_strv_free_ char **final_env = NULL, **our_env = NULL; + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; +@@ -2097,8 +2102,8 @@ static void service_enter_stop_post(Service *s, ServiceResult f) { + pidref_done(&s->control_pid); + + r = service_spawn(s, +- s->control_command_id, + s->control_command, ++ service_exec_flags(s->control_command_id, /* cred_flag = */ 0), + s->timeout_stop_usec, + &s->control_pid); + if (r < 0) { +@@ -2226,8 +2231,8 @@ static void service_enter_stop(Service *s, ServiceResult f) { + pidref_done(&s->control_pid); + + r = service_spawn(s, +- s->control_command_id, + s->control_command, ++ service_exec_flags(s->control_command_id, /* cred_flag = */ 0), + s->timeout_stop_usec, + &s->control_pid); + if (r < 0) { +@@ -2310,8 +2315,8 @@ static void service_enter_start_post(Service *s) { + pidref_done(&s->control_pid); + + r = service_spawn(s, +- s->control_command_id, + s->control_command, ++ service_exec_flags(s->control_command_id, /* cred_flag = */ 0), + s->timeout_start_usec, + &s->control_pid); + if (r < 0) { +@@ -2420,8 +2425,8 @@ static void service_enter_start(Service *s) { + timeout = s->timeout_start_usec; + + r = service_spawn(s, +- SERVICE_EXEC_START, + c, ++ service_exec_flags(SERVICE_EXEC_START, EXEC_SETUP_CREDENTIALS_FRESH), + timeout, + &pidref); + if (r < 0) { +@@ -2480,8 +2485,8 @@ static void service_enter_start_pre(Service *s) { + s->control_command_id = SERVICE_EXEC_START_PRE; + + r = service_spawn(s, +- s->control_command_id, + s->control_command, ++ service_exec_flags(s->control_command_id, /* cred_flag = */ 0), + s->timeout_start_usec, + &s->control_pid); + if (r < 0) { +@@ -2517,8 +2522,8 @@ static void service_enter_condition(Service *s) { + pidref_done(&s->control_pid); + + r = service_spawn(s, +- s->control_command_id, + s->control_command, ++ service_exec_flags(s->control_command_id, /* cred_flag = */ 0), + s->timeout_start_usec, + &s->control_pid); + +@@ -2635,8 +2640,8 @@ static void service_enter_reload(Service *s) { + pidref_done(&s->control_pid); + + r = service_spawn(s, +- s->control_command_id, + s->control_command, ++ service_exec_flags(s->control_command_id, /* cred_flag = */ 0), + s->timeout_start_usec, + &s->control_pid); + if (r < 0) { +@@ -2691,8 +2696,8 @@ static void service_run_next_control(Service *s) { + pidref_done(&s->control_pid); + + r = service_spawn(s, +- s->control_command_id, + s->control_command, ++ service_exec_flags(s->control_command_id, /* cred_flag = */ 0), + timeout, + &s->control_pid); + if (r < 0) { +@@ -2723,8 +2728,8 @@ static void service_run_next_main(Service *s) { + service_unwatch_main_pid(s); + + r = service_spawn(s, +- SERVICE_EXEC_START, + s->main_command, ++ service_exec_flags(SERVICE_EXEC_START, EXEC_SETUP_CREDENTIALS), + s->timeout_start_usec, + &pidref); + if (r < 0) { +diff --git a/test/units/testsuite-54.sh b/test/units/testsuite-54.sh +index bcbe7a1..50a6325 100755 +--- a/test/units/testsuite-54.sh ++++ b/test/units/testsuite-54.sh +@@ -3,6 +3,9 @@ + # shellcheck disable=SC2016 + set -eux + ++# shellcheck source=test/units/util.sh ++. "$(dirname "$0")"/util.sh ++ + systemd-analyze log-level debug + + run_with_cred_compare() { +@@ -302,6 +305,28 @@ systemd-run -p DynamicUser=yes -p 'LoadCredential=os:/etc/os-release' \ + --pipe \ + true | cmp /etc/os-release + ++# https://github.com/systemd/systemd/pull/24734#issuecomment-1925440546 ++# Also ExecStartPre= should be able to update creds ++dd if=/dev/urandom of=/tmp/cred-huge bs=600K count=1 ++chmod 777 /tmp/cred-huge ++systemd-run -p ProtectSystem=full \ ++ -p 'LoadCredential=huge:/tmp/cred-huge' \ ++ -p 'ExecStartPre=true' \ ++ -p 'ExecStartPre=bash -c "echo fresh >/tmp/cred-huge"' \ ++ --unit=test-54-huge-cred.service \ ++ --wait --pipe \ ++ systemd-creds cat huge | cmp - <(echo "fresh") ++rm /tmp/cred-huge ++ ++echo stable >/tmp/cred-stable ++systemd-run -p 'LoadCredential=stable:/tmp/cred-stable' \ ++ -p 'ExecStartPost=systemd-creds cat stable' \ ++ --unit=test-54-stable.service \ ++ --service-type=oneshot --wait --pipe \ ++ bash -c "echo bogus >/tmp/cred-stable" | cmp - <(echo "stable") ++assert_eq "$(cat /tmp/cred-stable)" "bogus" ++rm /tmp/cred-stable ++ + if ! systemd-detect-virt -q -c ; then + # Validate that the credential we inserted via the initrd logic arrived + test "$(systemd-creds cat --system myinitrdcred)" = "guatemala" +-- +2.43.0 + diff --git a/backport-core-service-allow-ExecStartPost-cmds-to-access-cred.patch b/backport-core-service-allow-ExecStartPost-cmds-to-access-cred.patch new file mode 100644 index 0000000..ca8497d --- /dev/null +++ b/backport-core-service-allow-ExecStartPost-cmds-to-access-cred.patch @@ -0,0 +1,27 @@ +From 39f4504de81c081e562139f1aab0a0388bc03b5f Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sun, 4 Feb 2024 19:38:20 +0800 +Subject: [PATCH] core/service: allow ExecStartPost= cmds to access creds + +Fixes #31194 +--- + src/core/service.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 41fe842db6..38934390f0 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -1608,8 +1608,7 @@ static ExecFlags service_exec_flags(ServiceExecCommand command_id) { + flags |= EXEC_APPLY_TTY_STDIN; + + /* All start phases get access to credentials */ +- // FIXME: SERVICE_EXEC_START_POST +- if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START)) ++ if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START, SERVICE_EXEC_START_POST)) + flags |= EXEC_WRITE_CREDENTIALS; + + if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START)) +-- +2.43.0 + diff --git a/backport-core-service-don-t-setup-credentials-for-ExecConditi.patch b/backport-core-service-don-t-setup-credentials-for-ExecConditi.patch new file mode 100644 index 0000000..c09fa91 --- /dev/null +++ b/backport-core-service-don-t-setup-credentials-for-ExecConditi.patch @@ -0,0 +1,34 @@ +From a145623bc403e410f41808a8e5cb31d29a52567c Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sun, 4 Feb 2024 19:36:06 +0800 +Subject: [PATCH] core/service: don't setup credentials for ExecCondition= and + ExecReload= + +This seems to be a mistake in #27279. I believe credentials should +not be made available to condition or reload tasks. In most cases +they're irrelevant from the actual job of the service. Also, currently +the first ExecCondition= or ExecReload= cannot access creds anyway, +making the incompatibility introduced negligible. + +If people actually come up with valid use cases, we can always +revisit this. +--- + src/core/service.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/service.c b/src/core/service.c +index ac9986994d..41fe842db6 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -1609,7 +1609,7 @@ static ExecFlags service_exec_flags(ServiceExecCommand command_id) { + + /* All start phases get access to credentials */ + // FIXME: SERVICE_EXEC_START_POST +- if (IN_SET(command_id, /* FIXME */ SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START, /* FIXME */ SERVICE_EXEC_RELOAD)) ++ if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START)) + flags |= EXEC_WRITE_CREDENTIALS; + + if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START)) +-- +2.43.0 + diff --git a/backport-core-service-introduce-service_exec_flags.patch b/backport-core-service-introduce-service_exec_flags.patch new file mode 100644 index 0000000..2c08712 --- /dev/null +++ b/backport-core-service-introduce-service_exec_flags.patch @@ -0,0 +1,268 @@ +From 81006ebbd70f16f41b8717e3a3d383ad79bbf1cd Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sun, 4 Feb 2024 00:25:03 +0800 +Subject: [PATCH] core/service: introduce service_exec_flags + +As suggested in +https://github.com/systemd/systemd/pull/31197#pullrequestreview-1861297477 + +Note that this slightly changes the behavior for +ExecReload=, ExecCondition= and ExecStartPost=. Will +be explained/corrected in later commits. +--- + src/core/service.c | 87 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 58 insertions(+), 29 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 8ea04c469d..a7bf1b8cfe 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -448,6 +448,7 @@ static void service_release_stdio_fd(Service *s) { + s->stdout_fd = asynchronous_close(s->stdout_fd); + s->stderr_fd = asynchronous_close(s->stderr_fd); + } ++ + static void service_done(Unit *u) { + Service *s = SERVICE(u); + +@@ -1594,15 +1595,51 @@ static Service *service_get_triggering_service(Service *s) { + return NULL; + } + ++static ExecFlags service_exec_flags(ServiceExecCommand command_id) { ++ /* All service main/control processes honor sandboxing and namespacing options (except those ++ explicitly excluded in service_spawn()) */ ++ ExecFlags flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT; ++ ++ assert(command_id >= 0); ++ assert(command_id < _SERVICE_EXEC_COMMAND_MAX); ++ ++ /* Control processes spawned before main process also get tty access */ ++ if (IN_SET(command_id, SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START, /* FIXME */ SERVICE_EXEC_STOP_POST)) ++ flags |= EXEC_APPLY_TTY_STDIN; ++ ++ /* All start phases get access to credentials */ ++ // FIXME: SERVICE_EXEC_START_POST ++ if (IN_SET(command_id, /* FIXME */ SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START, /* FIXME */ SERVICE_EXEC_RELOAD)) ++ flags |= EXEC_WRITE_CREDENTIALS; ++ ++ if (IN_SET(command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START)) ++ flags |= EXEC_SETENV_MONITOR_RESULT; ++ ++ if (command_id == SERVICE_EXEC_START) ++ return flags|EXEC_PASS_FDS|EXEC_SET_WATCHDOG; ++ ++ flags |= EXEC_IS_CONTROL; ++ ++ /* Put control processes spawned later than main process under .control sub-cgroup if appropriate */ ++ if (!IN_SET(command_id, SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE)) ++ flags |= EXEC_CONTROL_CGROUP; ++ ++ if (IN_SET(command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST)) ++ flags |= EXEC_SETENV_RESULT; ++ ++ return flags; ++} ++ + static int service_spawn_internal( + const char *caller, + Service *s, ++ ServiceExecCommand command_id, + ExecCommand *c, + usec_t timeout, +- ExecFlags flags, + PidRef *ret_pid) { + +- _cleanup_(exec_params_shallow_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(flags); ++ _cleanup_(exec_params_shallow_clear) ExecParameters exec_params = ++ EXEC_PARAMETERS_INIT(service_exec_flags(command_id)); + _cleanup_(sd_event_source_unrefp) sd_event_source *exec_fd_source = NULL; + _cleanup_strv_free_ char **final_env = NULL, **our_env = NULL; + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; +@@ -1622,7 +1659,7 @@ static int service_spawn_internal( + + assert(!s->exec_fd_event_source); + +- if (flags & EXEC_IS_CONTROL) { ++ if (FLAGS_SET(exec_params.flags, EXEC_IS_CONTROL)) { + /* If this is a control process, mask the permissions/chroot application if this is requested. */ + if (s->permissions_start_only) + exec_params.flags &= ~EXEC_APPLY_SANDBOXING; +@@ -1630,7 +1667,7 @@ static int service_spawn_internal( + exec_params.flags &= ~EXEC_APPLY_CHROOT; + } + +- if ((flags & EXEC_PASS_FDS) || ++ if (FLAGS_SET(exec_params.flags, EXEC_PASS_FDS) || + s->exec_context.std_input == EXEC_INPUT_SOCKET || + s->exec_context.std_output == EXEC_OUTPUT_SOCKET || + s->exec_context.std_error == EXEC_OUTPUT_SOCKET) { +@@ -1648,7 +1685,7 @@ static int service_spawn_internal( + log_unit_debug(UNIT(s), "Passing %zu fds to service", exec_params.n_socket_fds + exec_params.n_storage_fds); + } + +- if (!FLAGS_SET(flags, EXEC_IS_CONTROL) && s->type == SERVICE_EXEC) { ++ if (!FLAGS_SET(exec_params.flags, EXEC_IS_CONTROL) && s->type == SERVICE_EXEC) { + r = service_allocate_exec_fd(s, &exec_fd_source, &exec_params.exec_fd); + if (r < 0) + return r; +@@ -1662,7 +1699,7 @@ static int service_spawn_internal( + if (!our_env) + return -ENOMEM; + +- if (service_exec_needs_notify_socket(s, flags)) { ++ if (service_exec_needs_notify_socket(s, exec_params.flags)) { + if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0) + return -ENOMEM; + +@@ -1721,10 +1758,10 @@ static int service_spawn_internal( + + Service *env_source = NULL; + const char *monitor_prefix; +- if (flags & EXEC_SETENV_RESULT) { ++ if (FLAGS_SET(exec_params.flags, EXEC_SETENV_RESULT)) { + env_source = s; + monitor_prefix = ""; +- } else if (flags & EXEC_SETENV_MONITOR_RESULT) { ++ } else if (FLAGS_SET(exec_params.flags, EXEC_SETENV_MONITOR_RESULT)) { + env_source = service_get_triggering_service(s); + monitor_prefix = "MONITOR_"; + } +@@ -1742,18 +1779,15 @@ static int service_spawn_internal( + r = asprintf(our_env + n_env++, "%sEXIT_STATUS=%i", monitor_prefix, env_source->main_exec_status.status); + else + r = asprintf(our_env + n_env++, "%sEXIT_STATUS=%s", monitor_prefix, signal_to_string(env_source->main_exec_status.status)); +- + if (r < 0) + return -ENOMEM; + } + + if (env_source != s) { +- if (!sd_id128_is_null(UNIT(env_source)->invocation_id)) { +- r = asprintf(our_env + n_env++, "%sINVOCATION_ID=" SD_ID128_FORMAT_STR, +- monitor_prefix, SD_ID128_FORMAT_VAL(UNIT(env_source)->invocation_id)); +- if (r < 0) ++ if (!sd_id128_is_null(UNIT(env_source)->invocation_id)) ++ if (asprintf(our_env + n_env++, "%sINVOCATION_ID=" SD_ID128_FORMAT_STR, ++ monitor_prefix, SD_ID128_FORMAT_VAL(UNIT(env_source)->invocation_id)) < 0) + return -ENOMEM; +- } + + if (asprintf(our_env + n_env++, "%sUNIT=%s", monitor_prefix, UNIT(env_source)->id) < 0) + return -ENOMEM; +@@ -2050,9 +2084,9 @@ static void service_enter_stop_post(Service *s, ServiceResult f) { + pidref_done(&s->control_pid); + + r = service_spawn(s, ++ s->control_command_id, + s->control_command, + s->timeout_stop_usec, +- EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL|EXEC_SETENV_RESULT|EXEC_CONTROL_CGROUP, + &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'stop-post' task: %m"); +@@ -2173,9 +2207,9 @@ static void service_enter_stop(Service *s, ServiceResult f) { + pidref_done(&s->control_pid); + + r = service_spawn(s, ++ s->control_command_id, + s->control_command, + s->timeout_stop_usec, +- EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_SETENV_RESULT|EXEC_CONTROL_CGROUP, + &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'stop' task: %m"); +@@ -2257,9 +2291,9 @@ static void service_enter_start_post(Service *s) { + pidref_done(&s->control_pid); + + r = service_spawn(s, ++ s->control_command_id, + s->control_command, + s->timeout_start_usec, +- EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_CONTROL_CGROUP, + &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start-post' task: %m"); +@@ -2367,9 +2401,9 @@ static void service_enter_start(Service *s) { + timeout = s->timeout_start_usec; + + r = service_spawn(s, ++ SERVICE_EXEC_START, + c, + timeout, +- EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG|EXEC_WRITE_CREDENTIALS|EXEC_SETENV_MONITOR_RESULT, + &pidref); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start' task: %m"); +@@ -2427,9 +2461,9 @@ static void service_enter_start_pre(Service *s) { + s->control_command_id = SERVICE_EXEC_START_PRE; + + r = service_spawn(s, ++ s->control_command_id, + s->control_command, + s->timeout_start_usec, +- EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN|EXEC_SETENV_MONITOR_RESULT|EXEC_WRITE_CREDENTIALS, + &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start-pre' task: %m"); +@@ -2464,9 +2498,9 @@ static void service_enter_condition(Service *s) { + pidref_done(&s->control_pid); + + r = service_spawn(s, ++ s->control_command_id, + s->control_command, + s->timeout_start_usec, +- EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN, + &s->control_pid); + + if (r < 0) { +@@ -2575,9 +2609,9 @@ static void service_enter_reload(Service *s) { + pidref_done(&s->control_pid); + + r = service_spawn(s, ++ s->control_command_id, + s->control_command, + s->timeout_start_usec, +- EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_CONTROL_CGROUP, + &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'reload' task: %m"); +@@ -2631,14 +2665,9 @@ static void service_run_next_control(Service *s) { + pidref_done(&s->control_pid); + + r = service_spawn(s, ++ s->control_command_id, + s->control_command, + timeout, +- EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL| +- (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD) ? EXEC_WRITE_CREDENTIALS : 0)| +- (IN_SET(s->control_command_id, SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0)| +- (IN_SET(s->control_command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST) ? EXEC_SETENV_RESULT : 0)| +- (IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START) ? EXEC_SETENV_MONITOR_RESULT : 0)| +- (IN_SET(s->control_command_id, SERVICE_EXEC_START_POST, SERVICE_EXEC_RELOAD, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST) ? EXEC_CONTROL_CGROUP : 0), + &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to spawn next control task: %m"); +@@ -2668,9 +2697,9 @@ static void service_run_next_main(Service *s) { + service_unwatch_main_pid(s); + + r = service_spawn(s, ++ SERVICE_EXEC_START, + s->main_command, + s->timeout_start_usec, +- EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG|EXEC_SETENV_MONITOR_RESULT|EXEC_WRITE_CREDENTIALS, + &pidref); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to spawn next main task: %m"); +@@ -3896,7 +3925,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + s->control_command->command_next && + f == SERVICE_SUCCESS) { + +- /* There is another command to * execute, so let's do that. */ ++ /* There is another command to execute, so let's do that. */ + + log_unit_debug(u, "Running next control command for state %s.", service_state_to_string(s->state)); + service_run_next_control(s); +-- +2.43.0 + diff --git a/systemd.spec b/systemd.spec index b65615f..75a3d65 100644 --- a/systemd.spec +++ b/systemd.spec @@ -25,7 +25,7 @@ Name: systemd Url: https://systemd.io/ Version: 255 -Release: 48 +Release: 49 License: LGPL-2.1-or-later AND MIT AND GPL-2.0-or-later Summary: System and Service Manager @@ -115,6 +115,14 @@ Patch6658: backport-0002-coredump-get-rid-of-_META_MANDATORY_MAX.patch Patch6659: backport-CVE-2025-4598-coredump-use-d-in-kernel-core-pattern.patch Patch6660: backport-0001-coredump-also-stop-forwarding-non-dumpable-processes.patch Patch6661: backport-0002-coredump-get-rid-of-a-bogus-assertion.patch +#sync patches from systemd community +Patch6662: backport-core-exec-credential-add-missing-assertions.patch +Patch6663: backport-core-exec-credential-use-FOREACH_ARRAY-at-one-more-p.patch +Patch6664: backport-core-service-introduce-service_exec_flags.patch +Patch6665: backport-core-service-don-t-setup-credentials-for-ExecConditi.patch +Patch6666: backport-core-service-allow-ExecStartPost-cmds-to-access-cred.patch +Patch6667: backport-core-introduce-exec_params_need_credentials.patch +Patch6668: backport-core-reuse-credential-dir-across-start-and-start-pos.patch Patch9008: update-rtc-with-system-clock-when-shutdown.patch Patch9009: udev-add-actions-while-rename-netif-failed.patch @@ -1712,6 +1720,9 @@ fi %{_unitdir}/veritysetup.target %changelog +* Fri Aug 08 2025 Linux_zhang - 255-49 +- sync patches from systemd community + * Mon Aug 04 2025 mahailiang - 255-48 - add sw_64 support for virt -- Gitee