From: Lennart Poettering Date: Thu, 9 Jan 2025 22:57:32 +0000 (+0100) Subject: login: actually honour $HOME for chdir() X-Git-Tag: v2.42-start~95^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e269ff4bc32cb61e1d576d4f932b4027f5bc2c8;p=thirdparty%2Futil-linux.git login: actually honour $HOME for chdir() When login is almost done it chdir()'s into the user's home directory. It currently uses pwd->pw_dir, i.e the home dir actually assigned to the user. OTOH it explicitly allows overriding HOME (see comment in init_environ()), and explicitly imports PAM's env vars (which quite possibly contain $HOME) into its env block. This patch makes sure that HOME is *properly* overridable via the env var and via PAM: it actually honours it for the chdir(). (Background: I am working on a PAM module that under some conditions would like to redirect the home dir to some other dir, and while I can nicely set $HOME from the PAM module, it has not as much as effect as I wish, because whie the rest of userspace respects it login so far didn't and leaves the user in the wrong dir). --- diff --git a/include/logindefs.h b/include/logindefs.h index fa6aa2f07..24732ca70 100644 --- a/include/logindefs.h +++ b/include/logindefs.h @@ -30,6 +30,6 @@ extern const char *getlogindefs_str(const char *name, const char *dflt); extern void free_getlogindefs_data(void); extern int logindefs_setenv(const char *name, const char *conf, const char *dflt); extern int effective_access(const char *path, int mode); -extern int get_hushlogin_status(struct passwd *pwd, int force_check); +extern int get_hushlogin_status(struct passwd *pwd, const char *override_home, int force_check); #endif /* UTIL_LINUX_LOGINDEFS_H */ diff --git a/lib/logindefs.c b/lib/logindefs.c index 5f76ebd0f..7b6959921 100644 --- a/lib/logindefs.c +++ b/lib/logindefs.c @@ -467,7 +467,7 @@ int effective_access(const char *path, int mode) * BSD setreuid(). */ -int get_hushlogin_status(struct passwd *pwd, int force_check) +int get_hushlogin_status(struct passwd *pwd, const char *override_home, int force_check) { const char *files[] = { _PATH_HUSHLOGINS, _PATH_HUSHLOGIN, NULL }; const char *file; @@ -520,7 +520,7 @@ int get_hushlogin_status(struct passwd *pwd, int force_check) if (strlen(pwd->pw_dir) + strlen(file) + 2 > sizeof(buf)) continue; - if (snprintf(buf, sizeof(buf), "%s/%s", pwd->pw_dir, file) < 0) + if (snprintf(buf, sizeof(buf), "%s/%s", override_home ?: pwd->pw_dir, file) < 0) continue; if (force_check) { diff --git a/login-utils/login.c b/login-utils/login.c index 1d7dd3a67..321f9d6ce 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -1493,7 +1493,7 @@ int main(int argc, char **argv) } } - cxt.quiet = get_hushlogin_status(pwd, 1) == 1 ? 1 : 0; + cxt.quiet = get_hushlogin_status(pwd, pam_getenv(cxt.pamh, "HOME"), 1) == 1 ? 1 : 0; /* * Open PAM session (after successful authentication and account check). @@ -1543,8 +1543,9 @@ int main(int argc, char **argv) } /* wait until here to change directory! */ - if (chdir(pwd->pw_dir) < 0) { - warn(_("%s: change directory failed"), pwd->pw_dir); + const char *home = getenv("HOME") ?: pwd->pw_dir; + if (chdir(home) < 0) { + warn(_("%s: change directory failed"), home); if (!getlogindefs_bool("DEFAULT_HOME", 1)) exit(0); diff --git a/login-utils/lslogins.c b/login-utils/lslogins.c index 7c1ba6893..ebfdf6a79 100644 --- a/login-utils/lslogins.c +++ b/login-utils/lslogins.c @@ -904,7 +904,7 @@ static struct lslogins_user *get_user_info(struct lslogins_control *ctl, const c } break; case COL_HUSH_STATUS: - user->hushed = get_hushlogin_status(pwd, 0); + user->hushed = get_hushlogin_status(pwd, /* override_home= */ NULL, 0); if (user->hushed == -1) user->hushed = STATUS_UNKNOWN; break;