[git commit] login: new option LOGIN_SESSION_AS_CHILD

Denys Vlasenko vda.linux at googlemail.com
Wed Sep 14 06:41:38 UTC 2011


commit: http://git.busybox.net/busybox/commit/?id=378ab6819907fa9e439e93ed081c73c2351b4330
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Ian Wienand <ianw at vmware.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 debianutils/run_parts.c |    3 ++
 loginutils/Config.src   |   11 +++++++++
 loginutils/login.c      |   53 +++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c
index 65cbfc3..8f08f6d 100644
--- a/debianutils/run_parts.c
+++ b/debianutils/run_parts.c
@@ -66,6 +66,7 @@ struct globals {
 #define names (G.names)
 #define cur   (G.cur  )
 #define cmd   (G.cmd  )
+#define INIT_G() do { } while (0)
 
 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;
 	int ret;
 
+	INIT_G();
+
 #if ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS
 	applet_long_options = runparts_longopts;
 #endif
diff --git a/loginutils/Config.src b/loginutils/Config.src
index 0d7f50c..14ce534 100644
--- a/loginutils/Config.src
+++ b/loginutils/Config.src
@@ -205,6 +205,17 @@ config LOGIN
 	  Note that Busybox binary must be setuid root for this applet to
 	  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
 	bool "Support for PAM (Pluggable Authentication Modules)"
 	default n
diff --git a/loginutils/login.c b/loginutils/login.c
index 2f7b9b2..5343431 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -41,8 +41,6 @@ enum {
 	TTYNAME_SIZE = 32,
 };
 
-static char* short_tty;
-
 #if ENABLE_FEATURE_NOLOGIN
 static void die_if_nologin(void)
 {
@@ -74,7 +72,7 @@ static void die_if_nologin(void)
 #endif
 
 #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 */
 	parser_t *parser = config_open2("/etc/securetty", fopen_for_read);
@@ -89,7 +87,7 @@ static int check_securetty(void)
 	return buf != NULL;
 }
 #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
 
 #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);
 #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)
 {
 	int c, cntdown;
@@ -214,6 +235,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 	char *opt_host = NULL;
 	char *opt_user = opt_user; /* for compiler */
 	char *full_tty;
+	char *short_tty;
 	IF_SELINUX(security_context_t user_sid = NULL;)
 #if ENABLE_PAM
 	int pamret;
@@ -224,6 +246,9 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 	char pwdbuf[256];
 	char **pamenv;
 #endif
+#if ENABLE_LOGIN_SESSION_AS_CHILD
+	pid_t child_pid;
+#endif
 
 	username[0] = '\0';
 	signal(SIGALRM, alarm_handler);
@@ -359,7 +384,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 		if (opt & LOGIN_OPT_f)
 			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;
 
 		/* 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)
 		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.
 	 * _f_chown is safe wrt race t=ttyname(0);...;chown(t); */
-- 
1.7.3.4



More information about the busybox-cvs mailing list