* NEWS, src/su.c: When su receives a signal, wait for the child to

terminate (after sending a SIGTERM), and kill it only if it did
	not terminate by itself. No delay will be enforced if the child
	cooperates. See http://bugs.gentoo.org/282094
	* NEWS, man/su.1.xml: Document su's exit values.
This commit is contained in:
nekral-guest
2009-09-08 20:39:15 +00:00
parent da18e77e9a
commit 756700ddf3
4 changed files with 91 additions and 7 deletions

View File

@ -78,6 +78,8 @@
* Global variables
*/
char *Prog;
/* PID of the child, in case it needs to be killed */
static pid_t pid_child = 0;
/* not needed by sulog.c anymore */
static char name[BUFSIZ];
@ -103,11 +105,16 @@ extern size_t newenvc;
/* local function prototypes */
static void execve_shell (const char *shellstr,
char *args[],
char *const envp[]);
static RETSIGTYPE kill_child (int s);
#ifndef USE_PAM
static RETSIGTYPE die (int);
static int iswheel (const char *);
#endif /* !USE_PAM */
#ifndef USE_PAM
/*
* die - set or reset termio modes.
*
@ -126,7 +133,7 @@ static RETSIGTYPE die (int killed)
if (killed) {
closelog ();
exit (killed);
exit (128+killed);
}
}
@ -143,6 +150,18 @@ static int iswheel (const char *username)
}
#endif /* !USE_PAM */
static RETSIGTYPE kill_child (int unused(s))
{
if (0 != pid_child) {
(void) kill (pid_child, SIGKILL);
(void) fputs (_(" ...killed.\n"), stderr);
} else {
(void) fputs (_(" ...waiting for child to terminate.\n"),
stderr);
}
exit (255);
}
/* borrowed from GNU sh-utils' "su.c" */
static bool restricted_shell (const char *shellstr)
{
@ -252,6 +271,7 @@ static void run_shell (const char *shellstr, char *args[], bool doshell,
exit (1);
}
/* parent only */
pid_child = child;
sigfillset (&ourset);
if (sigprocmask (SIG_BLOCK, &ourset, NULL) != 0) {
(void) fprintf (stderr, "%s: signal malfunction\n", Prog);
@ -293,7 +313,9 @@ static void run_shell (const char *shellstr, char *args[], bool doshell,
}
if (caught) {
fprintf (stderr, "\nSession terminated, killing shell...");
(void) fputs ("\n", stderr);
(void) fputs (_("Session terminated, terminating shell..."),
stderr);
kill (child, SIGTERM);
}
@ -309,10 +331,11 @@ static void run_shell (const char *shellstr, char *args[], bool doshell,
ret = pam_end (pamh, PAM_SUCCESS);
if (caught) {
sleep (2);
kill (child, SIGKILL);
fprintf (stderr, " ...killed.\n");
exit (-1);
(void) signal (SIGALRM, kill_child);
(void) alarm (2);
(void) wait (&status);
(void) fputs (_(" ...terminated.\n"), stderr);
}
exit ((0 != WIFEXITED (status)) ? WEXITSTATUS (status)