diff options
author | davidxu <davidxu@FreeBSD.org> | 2003-03-27 01:32:51 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2003-03-27 01:32:51 +0000 |
commit | e173b93e2a0f714108298109cc176888cc9cc55b (patch) | |
tree | fb673180b713bced925fbdcb70b673150f60b4f7 /usr.bin/su | |
parent | ede5ebede767d6fee0a2d6efee34a51cc7b61bb7 (diff) | |
download | FreeBSD-src-e173b93e2a0f714108298109cc176888cc9cc55b.zip FreeBSD-src-e173b93e2a0f714108298109cc176888cc9cc55b.tar.gz |
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
Diffstat (limited to 'usr.bin/su')
-rw-r--r-- | usr.bin/su/su.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/usr.bin/su/su.c b/usr.bin/su/su.c index 16aa2e1..6d6c8da 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 |