]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/service: pass credentials to ExecReload*= if refreshed
authorMike Yuan <me@yhndnzj.com>
Sun, 14 Dec 2025 13:47:20 +0000 (14:47 +0100)
committerMike Yuan <me@yhndnzj.com>
Tue, 10 Feb 2026 20:54:13 +0000 (21:54 +0100)
Closes #35227

src/core/service.c
src/core/service.h

index 93253b45f49f462a8f022e471cc7d67bb434d528..49dd82ebb8ce2d7392f5846c9fae116b8e73f994 100644 (file)
@@ -1689,11 +1689,16 @@ static Service *service_get_triggering_service(Service *s) {
         return NULL;
 }
 
-static ExecFlags service_exec_flags(ServiceExecCommand command_id, ExecFlags cred_flag) {
+static ExecFlags service_exec_flags(
+                const Service *s,
+                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(s);
         assert(command_id >= 0);
         assert(command_id < _SERVICE_EXEC_COMMAND_MAX);
         assert((cred_flag & ~(EXEC_SETUP_CREDENTIALS_FRESH|EXEC_SETUP_CREDENTIALS)) == 0);
@@ -1725,6 +1730,12 @@ static ExecFlags service_exec_flags(ServiceExecCommand command_id, ExecFlags cre
         if (!IN_SET(command_id, SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE))
                 flags |= EXEC_CONTROL_CGROUP;
 
+        /* Pass credentials to ExecReload*= too, but only if the credentials are actually refreshed,
+         * to make sure they have the same understanding of the world as the main process. */
+        if (IN_SET(command_id, SERVICE_EXEC_RELOAD, SERVICE_EXEC_RELOAD_POST) &&
+            FLAGS_SET(s->refreshed_mask, SERVICE_RELOAD_CREDENTIALS))
+                flags |= EXEC_SETUP_CREDENTIALS;
+
         if (IN_SET(command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST))
                 flags |= EXEC_SETENV_RESULT;
 
@@ -2250,7 +2261,7 @@ static void service_enter_stop_post(Service *s, ServiceResult f) {
 
                 r = service_spawn(s,
                                   s->control_command,
-                                  service_exec_flags(s->control_command_id, /* cred_flag= */ 0),
+                                  service_exec_flags(s, s->control_command_id, /* cred_flag = */ 0),
                                   s->timeout_stop_usec,
                                   &s->control_pid);
                 if (r < 0) {
@@ -2362,7 +2373,7 @@ static void service_enter_stop(Service *s, ServiceResult f) {
 
                 r = service_spawn(s,
                                   s->control_command,
-                                  service_exec_flags(s->control_command_id, /* cred_flag= */ 0),
+                                  service_exec_flags(s, s->control_command_id, /* cred_flag = */ 0),
                                   s->timeout_stop_usec,
                                   &s->control_pid);
                 if (r < 0) {
@@ -2447,7 +2458,7 @@ static void service_enter_start_post(Service *s) {
 
                 r = service_spawn(s,
                                   s->control_command,
-                                  service_exec_flags(s->control_command_id, /* cred_flag= */ 0),
+                                  service_exec_flags(s, s->control_command_id, /* cred_flag = */ 0),
                                   s->timeout_start_usec,
                                   &s->control_pid);
                 if (r < 0) {
@@ -2557,7 +2568,7 @@ static void service_enter_start(Service *s) {
 
         r = service_spawn(s,
                           c,
-                          service_exec_flags(SERVICE_EXEC_START, EXEC_SETUP_CREDENTIALS_FRESH),
+                          service_exec_flags(s, SERVICE_EXEC_START, EXEC_SETUP_CREDENTIALS_FRESH),
                           timeout,
                           &pidref);
         if (r < 0) {
@@ -2617,7 +2628,7 @@ static void service_enter_start_pre(Service *s) {
 
                 r = service_spawn(s,
                                   s->control_command,
-                                  service_exec_flags(s->control_command_id, /* cred_flag= */ 0),
+                                  service_exec_flags(s, s->control_command_id, /* cred_flag = */ 0),
                                   s->timeout_start_usec,
                                   &s->control_pid);
                 if (r < 0) {
@@ -2653,7 +2664,7 @@ static void service_enter_condition(Service *s) {
 
                 r = service_spawn(s,
                                   s->control_command,
-                                  service_exec_flags(s->control_command_id, /* cred_flag= */ 0),
+                                  service_exec_flags(s, s->control_command_id, /* cred_flag = */ 0),
                                   s->timeout_start_usec,
                                   &s->control_pid);
                 if (r < 0) {
@@ -2757,7 +2768,7 @@ static void service_enter_reload_post(Service *s) {
 
                 r = service_spawn(s,
                                   s->control_command,
-                                  service_exec_flags(s->control_command_id, /* cred_flag= */ 0),
+                                  service_exec_flags(s, s->control_command_id, /* cred_flag = */ 0),
                                   s->timeout_start_usec,
                                   &s->control_pid);
                 if (r < 0) {
@@ -2832,7 +2843,7 @@ static void service_enter_reload(Service *s) {
 
                 r = service_spawn(s,
                                   s->control_command,
-                                  service_exec_flags(s->control_command_id, /* cred_flag= */ 0),
+                                  service_exec_flags(s, s->control_command_id, /* cred_flag = */ 0),
                                   s->timeout_start_usec,
                                   &s->control_pid);
                 if (r < 0) {
@@ -3063,7 +3074,7 @@ static void service_run_next_control(Service *s) {
 
         r = service_spawn(s,
                           s->control_command,
-                          service_exec_flags(s->control_command_id, /* cred_flag= */ 0),
+                          service_exec_flags(s, s->control_command_id, /* cred_flag = */ 0),
                           timeout,
                           &s->control_pid);
         if (r < 0) {
@@ -3094,7 +3105,7 @@ static void service_run_next_main(Service *s) {
 
         r = service_spawn(s,
                           s->main_command,
-                          service_exec_flags(SERVICE_EXEC_START, EXEC_SETUP_CREDENTIALS),
+                          service_exec_flags(s, SERVICE_EXEC_START, EXEC_SETUP_CREDENTIALS),
                           s->timeout_start_usec,
                           &pidref);
         if (r < 0) {
@@ -3275,6 +3286,7 @@ static int service_reload(Unit *u) {
         assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED));
 
         s->reload_result = SERVICE_SUCCESS;
+        s->refreshed_mask = 0;
 
         service_enter_refresh_extensions(s);
 
@@ -3495,6 +3507,21 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
 
         (void) serialize_usec(f, "reload-begin-usec", s->reload_begin_usec);
 
+        if (s->refreshed_mask > 0) {
+                _cleanup_strv_free_ char **l = NULL;
+                _cleanup_free_ char *t = NULL;
+
+                r = service_refresh_on_reload_to_strv(s->refreshed_mask, &l);
+                if (r < 0)
+                        return log_oom();
+
+                t = strv_join(l, " ");
+                if (!t)
+                        return log_oom();
+
+                (void) serialize_item(f, "refreshed-mask", t);
+        }
+
         return 0;
 }
 
@@ -3884,7 +3911,11 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
 
         } else if (streq(key, "reload-begin-usec"))
                 (void) deserialize_usec(value, &s->reload_begin_usec);
-        else
+        else if (streq(key, "refreshed-mask")) {
+                r = service_refresh_on_reload_from_string_many(value, &s->refreshed_mask);
+                if (r < 0)
+                        log_unit_debug_errno(u, r, "Failed to parse refresh-mask value: %s", value);
+        } else
                 log_unit_debug(u, "Unknown serialization key: %s", key);
 
         return 0;
@@ -4506,18 +4537,21 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                                 break;
 
                         case SERVICE_REFRESH_EXTENSIONS:
-                                if (f == SERVICE_SUCCESS)
+                                if (f == SERVICE_SUCCESS) {
+                                        s->refreshed_mask |= SERVICE_RELOAD_EXTENSIONS;
                                         service_enter_refresh_credentials(s);
-                                else
+                                else
                                         service_reload_finish(s, f);
                                 break;
 
                         case SERVICE_REFRESH_CREDENTIALS:
                                 if (f == SERVICE_SUCCESS ||
-                                    (f == SERVICE_FAILURE_EXIT_CODE && IN_SET(status, EXIT_NOTINSTALLED, EXIT_NOPERMISSION)))
+                                    (f == SERVICE_FAILURE_EXIT_CODE && IN_SET(status, EXIT_NOTINSTALLED, EXIT_NOPERMISSION))) {
+
                                         /* Refreshing asynchronously done, proceed to reload */
+                                        s->refreshed_mask |= f == SERVICE_SUCCESS ? SERVICE_RELOAD_CREDENTIALS : 0;
                                         service_enter_reload(s);
-                                else
+                                else
                                         service_reload_finish(s, f);
                                 break;
 
index 44882a6fd32a54a8b16b9cbad0e3f2b98897c7ad..9750b19ce285ffcf137a3274ba0b4e0424b980ea 100644 (file)
@@ -248,6 +248,7 @@ typedef struct Service {
 
         bool refresh_on_reload_set;
         ServiceRefreshOnReload refresh_on_reload_flags;
+        ServiceRefreshOnReload refreshed_mask;
 
         OOMPolicy oom_policy;