From a75fd4bf6eeb89e3c4c1556c96666390759f5d15 Mon Sep 17 00:00:00 2001 From: David Xu Date: Thu, 27 Mar 2003 01:32:51 +0000 Subject: [PATCH] Put child process in a different process group, ensure that the broadcast signal never affects su directly, some shells changes its pgrp at running or suspended time, so a broadcast SIGTSTP from child will mess up su's job control. Discussed with: bde --- usr.bin/su/su.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/usr.bin/su/su.c b/usr.bin/su/su.c index 16aa2e11ba16..6d6c8da669f9 100644 --- a/usr.bin/su/su.c +++ b/usr.bin/su/su.c @@ -130,7 +130,8 @@ main(int argc, char *argv[]) statusp, child_pid, child_pgrp, ret_pid, setmaclabel; char *username, *cleanenv, *class, shellbuf[MAXPATHLEN]; const char *p, *user, *shell, *mytty, **nargv; - struct sigaction sa, sa_int, sa_quit; + struct sigaction sa, sa_int, sa_quit, sa_pipe; + int temp, fds[2]; shell = class = cleanenv = NULL; asme = asthem = fastlogin = statusp = 0; @@ -326,20 +327,30 @@ main(int argc, char *argv[]) sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, &sa_int); sigaction(SIGQUIT, &sa, &sa_quit); + sigaction(SIGPIPE, &sa, &sa_pipe); sa.sa_handler = SIG_DFL; sigaction(SIGTSTP, &sa, NULL); statusp = 1; + if (pipe(fds) == -1) { + err(1, "pipe"); + PAM_END(); + exit(1); + } child_pid = fork(); switch (child_pid) { default: - while ((ret_pid = waitpid(child_pid, &statusp, WUNTRACED)) != -1) { + close(fds[0]); + setpgid(child_pid, child_pid); + tcsetpgrp(1, child_pid); + close(fds[1]); + sigaction(SIGPIPE, &sa_pipe, NULL); + while ((ret_pid = waitpid(child_pid, &statusp, WUNTRACED)) != + -1) { if (WIFSTOPPED(statusp)) { kill(getpid(), SIGSTOP); child_pgrp = getpgid(child_pid); - if (tcgetpgrp(1) == getpgrp()) { - tcsetpgrp(1, child_pgrp); - kill(child_pid, SIGCONT); - } + tcsetpgrp(1, child_pgrp); + kill(child_pid, SIGCONT); statusp = 1; continue; } @@ -354,8 +365,13 @@ main(int argc, char *argv[]) PAM_END(); exit(1); case 0: + close(fds[1]); + read(fds[0], &temp, 1); + close(fds[0]); + sigaction(SIGPIPE, &sa_pipe, NULL); sigaction(SIGINT, &sa_int, NULL); sigaction(SIGQUIT, &sa_quit, NULL); + /* * Set all user context except for: Environmental variables * Umask Login records (wtmp, etc) Path