core/service: pass credentials to ExecReload*= if refreshed

Closes #35227
This commit is contained in:
Mike Yuan
2026-02-10 21:54:13 +01:00
parent fff07be411
commit f385b3f3dd
2 changed files with 51 additions and 16 deletions
+50 -16
View 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;
+1
View File
@@ -248,6 +248,7 @@ typedef struct Service {
bool refresh_on_reload_set;
ServiceRefreshOnReload refresh_on_reload_flags;
ServiceRefreshOnReload refreshed_mask;
OOMPolicy oom_policy;