From: Lennart Poettering Date: Fri, 24 Jan 2025 10:17:55 +0000 (+0100) Subject: exec-invoke: respect $HOME set via PAM X-Git-Tag: v258-rc1~1410^2~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c554acd11d4dc778df1393c3a7e829a24de0455e;p=thirdparty%2Fsystemd.git exec-invoke: respect $HOME set via PAM This follows the same recent change in util-linux: https://github.com/util-linux/util-linux/pull/3354 i.e. we generally want that PAM modules can override $HOME and it is honoured for the CWD after login. (This renames the 'home' variable we maintained sofar to 'pwent_home', to clarify that it's the home directory listed in the struct passwd entry, and thus not necessarily the one actually used) --- diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 24e700a2892..265fe648a6e 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -3619,7 +3619,8 @@ static int apply_working_directory( const ExecContext *context, const ExecParameters *params, ExecRuntime *runtime, - const char *home) { + const char *pwent_home, + const char *const *env) { const char *wd; int r; @@ -3627,10 +3628,15 @@ static int apply_working_directory( assert(context); if (context->working_directory_home) { - if (!home) - return -ENXIO; - - wd = home; + /* Preferably use the data from $HOME, in case it was updated by a PAM module */ + wd = strv_env_get((char**) env, "HOME"); + if (!wd) { + /* If that's not available, use the data from the struct passwd entry: */ + if (!pwent_home) + return -ENXIO; + + wd = pwent_home; + } } else wd = empty_to_root(context->working_directory); @@ -4393,7 +4399,7 @@ int exec_invoke( _cleanup_free_ gid_t *supplementary_gids = NULL; const char *username = NULL, *groupname = NULL; _cleanup_free_ char *home_buffer = NULL, *memory_pressure_path = NULL, *own_user = NULL; - const char *home = NULL, *shell = NULL; + const char *pwent_home = NULL, *shell = NULL; char **final_argv = NULL; dev_t journal_stream_dev = 0; ino_t journal_stream_ino = 0; @@ -4645,7 +4651,7 @@ int exec_invoke( u = NULL; if (u) { - r = get_fixed_user(u, &username, &uid, &gid, &home, &shell); + r = get_fixed_user(u, &username, &uid, &gid, &pwent_home, &shell); if (r < 0) { *exit_status = EXIT_USER; return log_exec_error_errno(context, params, r, "Failed to determine user credentials: %m"); @@ -4677,7 +4683,7 @@ int exec_invoke( params->user_lookup_fd = safe_close(params->user_lookup_fd); - r = acquire_home(context, &home, &home_buffer); + r = acquire_home(context, &pwent_home, &home_buffer); if (r < 0) { *exit_status = EXIT_CHDIR; return log_exec_error_errno(context, params, r, "Failed to determine $HOME for the invoking user: %m"); @@ -4983,7 +4989,7 @@ int exec_invoke( params, cgroup_context, n_fds, - home, + pwent_home, username, shell, journal_stream_dev, @@ -5505,7 +5511,7 @@ int exec_invoke( * running this service might have the correct privilege to change to the working directory. Also, it * is absolutely 💣 crucial 💣 we applied all mount namespacing rearrangements before this, so that * the cwd cannot be used to pin directories outside of the sandbox. */ - r = apply_working_directory(context, params, runtime, home); + r = apply_working_directory(context, params, runtime, pwent_home, (const char* const*) accum_env); if (r < 0) { *exit_status = EXIT_CHDIR; return log_exec_error_errno(context, params, r, "Changing to the requested working directory failed: %m");