Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Jan 2014 22:50:01 GMT
From:      dfilter@FreeBSD.ORG (dfilter service)
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: misc/183495: commit references a PR
Message-ID:  <201401262250.s0QMo1Sl019433@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR misc/183495; it has been noted by GNATS.

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: misc/183495: commit references a PR
Date: Sun, 26 Jan 2014 22:49:33 +0000 (UTC)

 Author: jilles
 Date: Sun Jan 26 22:49:24 2014
 New Revision: 261193
 URL: http://svnweb.freebsd.org/changeset/base/261193
 
 Log:
   login: Clean up PAM and audit, then exit, on SIGHUP and SIGTERM.
   
   This avoids leaving stale entries in utmpx after the connection is closed on
   an open login session. It also allows a clean way (SIGTERM) to forcibly
   terminate a user's terminal session.
   
   This does not affect the situation for "hung" processes after the connection
   is closed. The foreground process group receives SIGHUP and the tty becomes
   inaccessible.
   
   Also replace all use of the obsolete signal() function with sigaction() (not
   only the part where it is actually required: SIGHUP and SIGTERM must mask
   the other as well when caught).
   
   PR:		misc/183495
   Reviewed by:	ed
 
 Modified:
   head/usr.bin/login/login.c
 
 Modified: head/usr.bin/login/login.c
 ==============================================================================
 --- head/usr.bin/login/login.c	Sun Jan 26 21:19:33 2014	(r261192)
 +++ head/usr.bin/login/login.c	Sun Jan 26 22:49:24 2014	(r261193)
 @@ -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 *, cons
  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);
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201401262250.s0QMo1Sl019433>