core/execute: always set $USER and introduce SetLoginEnvironment=

Before this commit, $USER, $HOME, $LOGNAME and $SHELL are only
set when User= is set for the unit. For system service, this
results in different behaviors depending on whether User=root is set.

$USER always makes sense on its own, so let's set it unconditionally.
Ideally $HOME should be set too, but it causes trouble when e.g. getty
passes '-p' to login(1), which then doesn't override $HOME. $LOGNAME and
$SHELL are more like "login environments", and are generally not
suitable for system services. Therefore, a new option SetLoginEnvironment=
is also added to control the latter three variables.

Fixes #23438

Replaces #8227
This commit is contained in:
Mike Yuan
2023-10-10 00:00:26 +08:00
parent 1c9433559a
commit 854eca4a95
7 changed files with 88 additions and 24 deletions
+4
View File
@@ -1273,6 +1273,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SetLoginEnvironment", "b", bus_property_get_tristate, offsetof(ExecContext, set_login_environment), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SetCredential", "a(say)", property_get_set_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SetCredentialEncrypted", "a(say)", property_get_set_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1730,6 +1731,9 @@ int bus_exec_context_set_transient_property(
if (streq(name, "Group"))
return bus_set_transient_user_relaxed(u, name, &c->group, message, flags, error);
if (streq(name, "SetLoginEnvironment"))
return bus_set_transient_tristate(u, name, &c->set_login_environment, message, flags, error);
if (streq(name, "TTYPath"))
return bus_set_transient_path(u, name, &c->tty_path, message, flags, error);
+29 -14
View File
@@ -1923,7 +1923,33 @@ static int build_environment(
our_env[n_env++] = x;
}
if (home) {
/* We query "root" if this is a system unit and User= is not specified. $USER is always set. $HOME
* could cause problem for e.g. getty, since login doesn't override $HOME, and $LOGNAME and $SHELL don't
* really make much sense since we're not logged in. Hence we conditionalize the three based on
* SetLoginEnvironment= switch. */
if (!c->user && !c->dynamic_user && p->runtime_scope == RUNTIME_SCOPE_SYSTEM) {
r = get_fixed_user("root", &username, NULL, NULL, &home, &shell);
if (r < 0)
return log_unit_error_errno(u, r, "Failed to determine user credentials for root: %m");
}
bool set_user_login_env = c->set_login_environment >= 0 ? c->set_login_environment : (c->user || c->dynamic_user);
if (username) {
x = strjoin("USER=", username);
if (!x)
return -ENOMEM;
our_env[n_env++] = x;
if (set_user_login_env) {
x = strjoin("LOGNAME=", username);
if (!x)
return -ENOMEM;
our_env[n_env++] = x;
}
}
if (home && set_user_login_env) {
x = strjoin("HOME=", home);
if (!x)
return -ENOMEM;
@@ -1932,19 +1958,7 @@ static int build_environment(
our_env[n_env++] = x;
}
if (username) {
x = strjoin("LOGNAME=", username);
if (!x)
return -ENOMEM;
our_env[n_env++] = x;
x = strjoin("USER=", username);
if (!x)
return -ENOMEM;
our_env[n_env++] = x;
}
if (shell) {
if (shell && set_user_login_env) {
x = strjoin("SHELL=", shell);
if (!x)
return -ENOMEM;
@@ -5262,6 +5276,7 @@ void exec_context_init(ExecContext *c) {
.tty_cols = UINT_MAX,
.private_mounts = -1,
.memory_ksm = -1,
.set_login_environment = -1,
};
FOREACH_ARRAY(d, c->directories, _EXEC_DIRECTORY_TYPE_MAX)
+2
View File
@@ -254,6 +254,8 @@ struct ExecContext {
char *group;
char **supplementary_groups;
int set_login_environment;
char *pam_name;
char *utmp_id;
+1
View File
@@ -19,6 +19,7 @@
{{type}}.User, config_parse_user_group_compat, 0, offsetof({{type}}, exec_context.user)
{{type}}.Group, config_parse_user_group_compat, 0, offsetof({{type}}, exec_context.group)
{{type}}.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof({{type}}, exec_context.supplementary_groups)
{{type}}.SetLoginEnvironment, config_parse_tristate, 0, offsetof({{type}}, exec_context.set_login_environment)
{{type}}.Nice, config_parse_exec_nice, 0, offsetof({{type}}, exec_context)
{{type}}.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof({{type}}, exec_context)
{{type}}.CoredumpFilter, config_parse_exec_coredump_filter, 0, offsetof({{type}}, exec_context)
+2 -1
View File
@@ -1078,7 +1078,8 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
"ProtectHostname",
"MemoryKSM",
"RestrictSUIDSGID",
"RootEphemeral"))
"RootEphemeral",
"SetLoginEnvironment"))
return bus_append_parse_boolean(m, field, eq);
if (STR_IN_SET(field, "ReadWriteDirectories",