From d162a7b978a98b910e410dc10a40d5de12db0419 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Jan 2022 23:19:11 +0100 Subject: [PATCH] sulogin: increase util-linux compatibility Change to root's HOME. Set some envvars. Steal ctty if necessary and possible. function old new delta sulogin_main 240 340 +100 setup_environment 225 233 +8 su_main 479 474 -5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 108/-5) Total: 103 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 18 ++++++++++-------- libbb/setup_environment.c | 8 ++++---- loginutils/sulogin.c | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index daa310776..a0ffbef62 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1726,15 +1726,16 @@ extern void selinux_or_die(void) FAST_FUNC; /* setup_environment: - * if chdir pw->pw_dir: ok: else if to_tmp == 1: goto /tmp else: goto / or die - * if clear_env = 1: cd(pw->pw_dir), clear environment, then set + * if !SETUP_ENV_NO_CHDIR: + * if cd(pw->pw_dir): ok: else if SETUP_ENV_TO_TMP: cd(/tmp) else: cd(/) or die + * if SETUP_ENV_CLEARENV: cd(pw->pw_dir), clear environment, then set * TERM=(old value) * USER=pw->pw_name, LOGNAME=pw->pw_name * PATH=bb_default_[root_]path * HOME=pw->pw_dir * SHELL=shell - * else if change_env = 1: - * if not root (if pw->pw_uid != 0): + * else if SETUP_ENV_CHANGEENV: + * if not root (if pw->pw_uid != 0) or if SETUP_ENV_CHANGEENV_LOGNAME: * USER=pw->pw_name, LOGNAME=pw->pw_name * HOME=pw->pw_dir * SHELL=shell @@ -1743,10 +1744,11 @@ extern void selinux_or_die(void) FAST_FUNC; * NB: CHANGEENV and CLEARENV use setenv() - this leaks memory! * If setup_environment() is used is vforked child, this leaks memory _in parent too_! */ -#define SETUP_ENV_CHANGEENV (1 << 0) -#define SETUP_ENV_CLEARENV (1 << 1) -#define SETUP_ENV_TO_TMP (1 << 2) -#define SETUP_ENV_NO_CHDIR (1 << 4) +#define SETUP_ENV_CHANGEENV (1 << 0) +#define SETUP_ENV_CHANGEENV_LOGNAME (1 << 1) +#define SETUP_ENV_CLEARENV (1 << 2) +#define SETUP_ENV_TO_TMP (1 << 3) +#define SETUP_ENV_NO_CHDIR (1 << 4) void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC; void nuke_str(char *str) FAST_FUNC; #if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM diff --git a/libbb/setup_environment.c b/libbb/setup_environment.c index f8de44967..df2983958 100644 --- a/libbb/setup_environment.c +++ b/libbb/setup_environment.c @@ -54,15 +54,15 @@ void FAST_FUNC setup_environment(const char *shell, int flags, const struct pass xsetenv("TERM", term); xsetenv("PATH", (pw->pw_uid ? bb_default_path : bb_default_root_path)); goto shortcut; - // No, gcc (4.2.1) is not clever enougn to do it itself. + // No, gcc (4.2.1) is not clever enough to do it itself. //xsetenv("USER", pw->pw_name); //xsetenv("LOGNAME", pw->pw_name); //xsetenv("HOME", pw->pw_dir); //xsetenv("SHELL", shell); } else if (flags & SETUP_ENV_CHANGEENV) { - /* Set HOME, SHELL, and if not becoming a super-user, - * USER and LOGNAME. */ - if (pw->pw_uid) { + /* Set HOME, SHELL, and if not becoming a super-user + * or if SETUP_ENV_CHANGEENV_LOGNAME, USER and LOGNAME. */ + if ((flags & SETUP_ENV_CHANGEENV_LOGNAME) || pw->pw_uid != 0) { shortcut: xsetenv("USER", pw->pw_name); xsetenv("LOGNAME", pw->pw_name); diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 69d8b5ec7..5f1c1178f 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c @@ -28,6 +28,7 @@ int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int sulogin_main(int argc UNUSED_PARAM, char **argv) { + int tsid; int timeout = 0; struct passwd *pwd; const char *shell; @@ -88,6 +89,28 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) if (!shell) shell = pwd->pw_shell; + /* util-linux 2.36.1 compat: cd to root's HOME, set a few envvars */ + setup_environment(shell, SETUP_ENV_CHANGEENV | SETUP_ENV_CHANGEENV_LOGNAME, pwd); + // no SETUP_ENV_CLEARENV + // SETUP_ENV_CHANGEENV[+LOGNAME] - set HOME, SHELL, USER,and LOGNAME + // no SETUP_ENV_NO_CHDIR - IOW: cd to $HOME + + /* util-linux 2.36.1 compat: steal ctty if we don't have it yet + * (yes, util-linux uses force=1) */ + tsid = tcgetsid(STDIN_FILENO); + if (tsid < 0 || getpid() != tsid) { + if (ioctl(STDIN_FILENO, TIOCSCTTY, /*force:*/ (long)1) != 0) { +// bb_perror_msg("TIOCSCTTY1 tsid:%d", tsid); + if (setsid() > 0) { +// bb_error_msg("done setsid()"); + /* If it still does not work, ignore */ + if (ioctl(STDIN_FILENO, TIOCSCTTY, /*force:*/ (long)1) != 0) { +// bb_perror_msg("TIOCSCTTY2 tsid:%d", tsid); + } + } + } + } + /* Exec login shell with no additional parameters. Never returns. */ exec_login_shell(shell); }