summaryrefslogtreecommitdiffstats
path: root/usr.bin/su
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2003-03-27 01:32:51 +0000
committerdavidxu <davidxu@FreeBSD.org>2003-03-27 01:32:51 +0000
commite173b93e2a0f714108298109cc176888cc9cc55b (patch)
treefb673180b713bced925fbdcb70b673150f60b4f7 /usr.bin/su
parentede5ebede767d6fee0a2d6efee34a51cc7b61bb7 (diff)
downloadFreeBSD-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.c28
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
OpenPOWER on IntegriCloud