login: new option LOGIN_SESSION_AS_CHILD

Signed-off-by: Ian Wienand <ianw@vmware.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Ian Wienand 2011-09-14 08:41:38 +02:00 committed by Denys Vlasenko
parent a221bc5f99
commit 378ab68199
3 changed files with 61 additions and 6 deletions

View File

@ -66,6 +66,7 @@ struct globals {
#define names (G.names) #define names (G.names)
#define cur (G.cur ) #define cur (G.cur )
#define cmd (G.cmd ) #define cmd (G.cmd )
#define INIT_G() do { } while (0)
enum { NUM_CMD = (COMMON_BUFSIZE - sizeof(G)) / sizeof(cmd[0]) - 1 }; enum { NUM_CMD = (COMMON_BUFSIZE - sizeof(G)) / sizeof(cmd[0]) - 1 };
@ -143,6 +144,8 @@ int run_parts_main(int argc UNUSED_PARAM, char **argv)
unsigned n; unsigned n;
int ret; int ret;
INIT_G();
#if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS #if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
applet_long_options = runparts_longopts; applet_long_options = runparts_longopts;
#endif #endif

View File

@ -205,6 +205,17 @@ config LOGIN
Note that Busybox binary must be setuid root for this applet to Note that Busybox binary must be setuid root for this applet to
work properly. work properly.
config LOGIN_SESSION_AS_CHILD
bool "Run logged in session in a child process"
default y if PAM
depends on LOGIN
help
Run the logged in session in a child process. This allows
login to clean up things such as utmp entries or PAM sessions
when the login session is complete. If you use PAM, you
almost always would want this to be set to Y, else PAM session
will not be cleaned up.
config PAM config PAM
bool "Support for PAM (Pluggable Authentication Modules)" bool "Support for PAM (Pluggable Authentication Modules)"
default n default n

View File

@ -41,8 +41,6 @@ enum {
TTYNAME_SIZE = 32, TTYNAME_SIZE = 32,
}; };
static char* short_tty;
#if ENABLE_FEATURE_NOLOGIN #if ENABLE_FEATURE_NOLOGIN
static void die_if_nologin(void) static void die_if_nologin(void)
{ {
@ -74,7 +72,7 @@ static void die_if_nologin(void)
#endif #endif
#if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM #if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM
static int check_securetty(void) static int check_securetty(const char *short_tty)
{ {
char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */ char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */
parser_t *parser = config_open2("/etc/securetty", fopen_for_read); parser_t *parser = config_open2("/etc/securetty", fopen_for_read);
@ -89,7 +87,7 @@ static int check_securetty(void)
return buf != NULL; return buf != NULL;
} }
#else #else
static ALWAYS_INLINE int check_securetty(void) { return 1; } static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; }
#endif #endif
#if ENABLE_SELINUX #if ENABLE_SELINUX
@ -142,6 +140,29 @@ static void run_login_script(struct passwd *pw, char *full_tty)
void run_login_script(struct passwd *pw, char *full_tty); void run_login_script(struct passwd *pw, char *full_tty);
#endif #endif
#if ENABLE_LOGIN_SESSION_AS_CHILD && ENABLE_PAM
static void login_pam_end(pam_handle_t *pamh)
{
int pamret;
pamret = pam_setcred(pamh, PAM_DELETE_CRED);
if (pamret != PAM_SUCCESS) {
bb_error_msg("pam_%s failed: %s (%d)", "setcred",
pam_strerror(pamh, pamret), pamret);
}
pamret = pam_close_session(pamh, 0);
if (pamret != PAM_SUCCESS) {
bb_error_msg("pam_%s failed: %s (%d)", "close_session",
pam_strerror(pamh, pamret), pamret);
}
pamret = pam_end(pamh, pamret);
if (pamret != PAM_SUCCESS) {
bb_error_msg("pam_%s failed: %s (%d)", "end",
pam_strerror(pamh, pamret), pamret);
}
}
#endif /* ENABLE_PAM */
static void get_username_or_die(char *buf, int size_buf) static void get_username_or_die(char *buf, int size_buf)
{ {
int c, cntdown; int c, cntdown;
@ -214,6 +235,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
char *opt_host = NULL; char *opt_host = NULL;
char *opt_user = opt_user; /* for compiler */ char *opt_user = opt_user; /* for compiler */
char *full_tty; char *full_tty;
char *short_tty;
IF_SELINUX(security_context_t user_sid = NULL;) IF_SELINUX(security_context_t user_sid = NULL;)
#if ENABLE_PAM #if ENABLE_PAM
int pamret; int pamret;
@ -224,6 +246,9 @@ int login_main(int argc UNUSED_PARAM, char **argv)
char pwdbuf[256]; char pwdbuf[256];
char **pamenv; char **pamenv;
#endif #endif
#if ENABLE_LOGIN_SESSION_AS_CHILD
pid_t child_pid;
#endif
username[0] = '\0'; username[0] = '\0';
signal(SIGALRM, alarm_handler); signal(SIGALRM, alarm_handler);
@ -359,7 +384,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
if (opt & LOGIN_OPT_f) if (opt & LOGIN_OPT_f)
break; /* -f USER: success without asking passwd */ break; /* -f USER: success without asking passwd */
if (pw->pw_uid == 0 && !check_securetty()) if (pw->pw_uid == 0 && !check_securetty(short_tty))
goto auth_failed; goto auth_failed;
/* Don't check the password if password entry is empty (!) */ /* Don't check the password if password entry is empty (!) */
@ -393,7 +418,23 @@ int login_main(int argc UNUSED_PARAM, char **argv)
if (pw->pw_uid != 0) if (pw->pw_uid != 0)
die_if_nologin(); die_if_nologin();
IF_SELINUX(initselinux(username, full_tty, &user_sid));
#if ENABLE_LOGIN_SESSION_AS_CHILD
child_pid = vfork();
if (child_pid != 0) {
if (child_pid < 0)
bb_perror_msg("vfork");
else {
if (safe_waitpid(child_pid, NULL, 0) == -1)
bb_perror_msg("waitpid");
update_utmp(child_pid, DEAD_PROCESS, NULL, NULL, NULL);
}
IF_PAM(login_pam_end(pamh);)
return 0;
}
#endif
IF_SELINUX(initselinux(username, full_tty, &user_sid);)
/* Try these, but don't complain if they fail. /* Try these, but don't complain if they fail.
* _f_chown is safe wrt race t=ttyname(0);...;chown(t); */ * _f_chown is safe wrt race t=ttyname(0);...;chown(t); */