diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 632f1b6281c..2b7c923b5e6 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -220,9 +220,9 @@ static int synthesize_user_creds( if (ret_gid) *ret_gid = GID_NOBODY; if (ret_home) - *ret_home = FLAGS_SET(flags, USER_CREDS_CLEAN) ? NULL : "/"; + *ret_home = FLAGS_SET(flags, USER_CREDS_SUPPRESS_PLACEHOLDER) ? NULL : "/"; if (ret_shell) - *ret_shell = FLAGS_SET(flags, USER_CREDS_CLEAN) ? NULL : NOLOGIN; + *ret_shell = FLAGS_SET(flags, USER_CREDS_SUPPRESS_PLACEHOLDER) ? NULL : NOLOGIN; return 0; } @@ -244,6 +244,7 @@ int get_user_creds( assert(username); assert(*username); + assert((ret_home || ret_shell) || !(flags & (USER_CREDS_SUPPRESS_PLACEHOLDER|USER_CREDS_CLEAN))); if (!FLAGS_SET(flags, USER_CREDS_PREFER_NSS) || (!ret_home && !ret_shell)) { @@ -315,16 +316,14 @@ int get_user_creds( if (ret_home) /* Note: we don't insist on normalized paths, since there are setups that have /./ in the path */ - *ret_home = (FLAGS_SET(flags, USER_CREDS_CLEAN) && - (empty_or_root(p->pw_dir) || - !path_is_valid(p->pw_dir) || - !path_is_absolute(p->pw_dir))) ? NULL : p->pw_dir; + *ret_home = (FLAGS_SET(flags, USER_CREDS_SUPPRESS_PLACEHOLDER) && empty_or_root(p->pw_dir)) || + (FLAGS_SET(flags, USER_CREDS_CLEAN) && (!path_is_valid(p->pw_dir) || !path_is_absolute(p->pw_dir))) + ? NULL : p->pw_dir; if (ret_shell) - *ret_shell = (FLAGS_SET(flags, USER_CREDS_CLEAN) && - (shell_is_placeholder(p->pw_shell) || - !path_is_valid(p->pw_shell) || - !path_is_absolute(p->pw_shell))) ? NULL : p->pw_shell; + *ret_shell = (FLAGS_SET(flags, USER_CREDS_SUPPRESS_PLACEHOLDER) && shell_is_placeholder(p->pw_shell)) || + (FLAGS_SET(flags, USER_CREDS_CLEAN) && (!path_is_valid(p->pw_shell) || !path_is_absolute(p->pw_shell))) + ? NULL : p->pw_shell; if (patch_username) *username = p->pw_name; diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 4858a9cb587..6f221ebfb0b 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -48,9 +48,10 @@ static inline bool shell_is_placeholder(const char *shell) { } typedef enum UserCredsFlags { - USER_CREDS_PREFER_NSS = 1 << 0, /* if set, only synthesize user records if database lacks them. Normally we bypass the userdb entirely for the records we can synthesize */ - USER_CREDS_ALLOW_MISSING = 1 << 1, /* if a numeric UID string is resolved, be OK if there's no record for it */ - USER_CREDS_CLEAN = 1 << 2, /* try to clean up shell and home fields with invalid data */ + USER_CREDS_PREFER_NSS = 1 << 0, /* if set, only synthesize user records if database lacks them. Normally we bypass the userdb entirely for the records we can synthesize */ + USER_CREDS_ALLOW_MISSING = 1 << 1, /* if a numeric UID string is resolved, be OK if there's no record for it */ + USER_CREDS_CLEAN = 1 << 2, /* try to clean up shell and home fields with invalid data */ + USER_CREDS_SUPPRESS_PLACEHOLDER = 1 << 3, /* suppress home and/or shell fields if value is placeholder (root/empty/nologin) */ } UserCredsFlags; int get_user_creds(const char **username, uid_t *ret_uid, gid_t *ret_gid, const char **ret_home, const char **ret_shell, UserCredsFlags flags); diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 2f8924cd018..517727a7b20 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -858,7 +858,7 @@ static int get_fixed_user( /* Note that we don't set $HOME or $SHELL if they are not particularly enlightening anyway * (i.e. are "/" or "/bin/nologin"). */ - r = get_user_creds(&user_or_uid, ret_uid, ret_gid, ret_home, ret_shell, USER_CREDS_CLEAN); + r = get_user_creds(&user_or_uid, ret_uid, ret_gid, ret_home, ret_shell, USER_CREDS_CLEAN|USER_CREDS_SUPPRESS_PLACEHOLDER); if (r < 0) return r; diff --git a/src/run/run.c b/src/run/run.c index c62dce8950f..1b13e74b83c 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -2297,7 +2297,8 @@ static int start_transient_scope(sd_bus *bus) { uid_t uid; gid_t gid; - r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell, USER_CREDS_CLEAN|USER_CREDS_PREFER_NSS); + r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell, + USER_CREDS_CLEAN|USER_CREDS_SUPPRESS_PLACEHOLDER|USER_CREDS_PREFER_NSS); if (r < 0) return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);