--- util-linux-2.13-pre1/login-utils/login.c.ctty3 2005-08-02 18:10:24.000000000 +0200 +++ util-linux-2.13-pre1/login-utils/login.c 2005-08-15 15:51:35.000000000 +0200 @@ -285,7 +285,21 @@ updwtmp(_PATH_BTMP, &ut); #endif } -#endif /* HAVE_SECURITY_PAM_MISC_H */ + +static int childPid = 0; +static volatile int got_sig = 0; + +static void +parent_sig_handler(int signal) +{ + if(childPid) + kill(-childPid, signal); + else + got_sig = 1; + if(signal == SIGTERM) + kill(-childPid, SIGHUP); /* because the shell often ignores SIGTERM */ +} +#endif /* HAVE_SECURITY_PAM_MISC_H */ int main(int argc, char **argv) @@ -307,7 +321,7 @@ int retcode; pam_handle_t *pamh = NULL; struct pam_conv conv = { misc_conv, NULL }; - pid_t childPid; + struct sigaction sa, oldsa_hup, oldsa_term; #else char *salt, *pp; #endif @@ -1023,7 +1037,18 @@ * We must fork before setuid() because we need to call * pam_close_session() as root. */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + sigaction(SIGINT, &sa, NULL); + + sigaction(SIGHUP, &sa, &oldsa_hup); /* ignore while we detach from the tty */ + ioctl(0, TIOCNOTTY, NULL); + + sa.sa_handler = parent_sig_handler; + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGTERM, &sa, &oldsa_term); + closelog(); childPid = fork(); if (childPid < 0) { int errsv = errno; @@ -1034,19 +1059,20 @@ } if (childPid) { - /* parent - wait for child to finish, then cleanup session */ - signal(SIGHUP, SIG_IGN); - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGTSTP, SIG_IGN); - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - - wait(NULL); + close(0); close(1); close(2); + sa.sa_handler = SIG_IGN; + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + while(wait(NULL) == -1 && errno == EINTR) /**/ ; + openlog("login", LOG_ODELAY, LOG_AUTHPRIV); PAM_END; exit(0); } + sigaction(SIGHUP, &oldsa_hup, NULL); + sigaction(SIGTERM, &oldsa_term, NULL); + if(got_sig) exit(1); + /* child */ /* * Problem: if the user's shell is a shell like ash that doesnt do @@ -1058,14 +1084,15 @@ setsid(); /* make sure we have a controlling tty */ - opentty(ttyn); openlog("login", LOG_ODELAY, LOG_AUTHPRIV); /* reopen */ /* * TIOCSCTTY: steal tty from other process group. */ - if (ioctl(0, TIOCSCTTY, 1)) - syslog(LOG_ERR, _("TIOCSCTTY failed: %m")); + if (ioctl(0, TIOCSCTTY, (char *)1)) { + syslog(LOG_ERR, _("Couldn't set controlling terminal: %s"), strerror(errno)); + exit(1); + } #endif signal(SIGINT, SIG_DFL);