summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.bin/login/login.c95
1 files changed, 77 insertions, 18 deletions
diff --git a/usr.bin/login/login.c b/usr.bin/login/login.c
index 1de440b..e2af83f 100644
--- a/usr.bin/login/login.c
+++ b/usr.bin/login/login.c
@@ -83,6 +83,7 @@ __FBSDID("$FreeBSD$");
static int auth_pam(void);
static void bail(int, int);
+static void bail_internal(int, int, int);
static int export(const char *);
static void export_pam_environment(void);
static int motd(const char *);
@@ -94,6 +95,7 @@ static void refused(const char *, const char *, int);
static const char *stypeof(char *);
static void sigint(int);
static void timedout(int);
+static void bail_sig(int);
static void usage(void);
#define TTYGRPNAME "tty" /* group to own ttys */
@@ -172,13 +174,18 @@ main(int argc, char *argv[])
login_cap_t *lc = NULL;
login_cap_t *lc_user = NULL;
pid_t pid;
+ sigset_t mask, omask;
+ struct sigaction sa;
#ifdef USE_BSM_AUDIT
char auditsuccess = 1;
#endif
- (void)signal(SIGQUIT, SIG_IGN);
- (void)signal(SIGINT, SIG_IGN);
- (void)signal(SIGHUP, SIG_IGN);
+ sa.sa_flags = SA_RESTART;
+ (void)sigfillset(&sa.sa_mask);
+ sa.sa_handler = SIG_IGN;
+ (void)sigaction(SIGQUIT, &sa, NULL);
+ (void)sigaction(SIGINT, &sa, NULL);
+ (void)sigaction(SIGHUP, &sa, NULL);
if (setjmp(timeout_buf)) {
if (failures)
badlogin(username);
@@ -186,7 +193,8 @@ main(int argc, char *argv[])
timeout);
bail(NO_SLEEP_EXIT, 0);
}
- (void)signal(SIGALRM, timedout);
+ sa.sa_handler = timedout;
+ (void)sigaction(SIGALRM, &sa, NULL);
(void)alarm(timeout);
(void)setpriority(PRIO_PROCESS, 0, 0);
@@ -370,7 +378,14 @@ main(int argc, char *argv[])
/* committed to login -- turn off timeout */
(void)alarm((u_int)0);
- (void)signal(SIGHUP, SIG_DFL);
+
+ (void)sigemptyset(&mask);
+ (void)sigaddset(&mask, SIGHUP);
+ (void)sigaddset(&mask, SIGTERM);
+ (void)sigprocmask(SIG_BLOCK, &mask, &omask);
+ sa.sa_handler = bail_sig;
+ (void)sigaction(SIGHUP, &sa, NULL);
+ (void)sigaction(SIGTERM, &sa, NULL);
endpwent();
@@ -550,10 +565,17 @@ main(int argc, char *argv[])
/*
* Parent: wait for child to finish, then clean up
* session.
+ *
+ * If we get SIGHUP or SIGTERM, clean up the session
+ * and exit right away. This will make the terminal
+ * inaccessible and send SIGHUP to the foreground
+ * process group.
*/
int status;
setproctitle("-%s [pam]", getprogname());
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
waitpid(pid, &status, 0);
+ (void)sigprocmask(SIG_BLOCK, &mask, NULL);
bail(NO_SLEEP_EXIT, 0);
}
@@ -627,10 +649,15 @@ main(int argc, char *argv[])
login_close(lc_user);
login_close(lc);
- (void)signal(SIGALRM, SIG_DFL);
- (void)signal(SIGQUIT, SIG_DFL);
- (void)signal(SIGINT, SIG_DFL);
- (void)signal(SIGTSTP, SIG_IGN);
+ sa.sa_handler = SIG_DFL;
+ (void)sigaction(SIGALRM, &sa, NULL);
+ (void)sigaction(SIGQUIT, &sa, NULL);
+ (void)sigaction(SIGINT, &sa, NULL);
+ (void)sigaction(SIGTERM, &sa, NULL);
+ (void)sigaction(SIGHUP, &sa, NULL);
+ sa.sa_handler = SIG_IGN;
+ (void)sigaction(SIGTSTP, &sa, NULL);
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
/*
* Login shells have a leading '-' in front of argv[0]
@@ -847,17 +874,20 @@ sigint(int signo __unused)
static int
motd(const char *motdfile)
{
- sig_t oldint;
+ struct sigaction newint, oldint;
FILE *f;
int ch;
if ((f = fopen(motdfile, "r")) == NULL)
return (-1);
motdinterrupt = 0;
- oldint = signal(SIGINT, sigint);
+ newint.sa_handler = sigint;
+ newint.sa_flags = 0;
+ sigfillset(&newint.sa_mask);
+ sigaction(SIGINT, &newint, &oldint);
while ((ch = fgetc(f)) != EOF && !motdinterrupt)
putchar(ch);
- signal(SIGINT, oldint);
+ sigaction(SIGINT, &oldint, NULL);
if (ch != EOF || ferror(f)) {
fclose(f);
return (-1);
@@ -966,12 +996,10 @@ pam_cleanup(void)
}
}
-/*
- * Exit, optionally after sleeping a few seconds
- */
-void
-bail(int sec, int eval)
+static void
+bail_internal(int sec, int eval, int signo)
{
+ struct sigaction sa;
pam_cleanup();
#ifdef USE_BSM_AUDIT
@@ -979,5 +1007,36 @@ bail(int sec, int eval)
audit_logout();
#endif
(void)sleep(sec);
- exit(eval);
+ if (signo == 0)
+ exit(eval);
+ else {
+ sa.sa_handler = SIG_DFL;
+ sa.sa_flags = 0;
+ (void)sigemptyset(&sa.sa_mask);
+ (void)sigaction(signo, &sa, NULL);
+ (void)sigaddset(&sa.sa_mask, signo);
+ (void)sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
+ raise(signo);
+ exit(128 + signo);
+ }
+}
+
+/*
+ * Exit, optionally after sleeping a few seconds
+ */
+static void
+bail(int sec, int eval)
+{
+ bail_internal(sec, eval, 0);
+}
+
+/*
+ * Exit because of a signal.
+ * This is not async-signal safe, so only call async-signal safe functions
+ * while the signal is unmasked.
+ */
+static void
+bail_sig(int signo)
+{
+ bail_internal(NO_SLEEP_EXIT, 0, signo);
}
OpenPOWER on IntegriCloud