summaryrefslogtreecommitdiffstats
path: root/login-utils/login.c
diff options
context:
space:
mode:
authorKarel Zak2007-03-08 22:21:15 +0100
committerKarel Zak2007-03-08 22:21:15 +0100
commit649efbb369506a2096811186015b33a80cf15b94 (patch)
tree3f795469a1ada6071ca9e58719fa3a8a9ba39b99 /login-utils/login.c
parentlogin: improve work with signals (diff)
downloadkernel-qcow2-util-linux-649efbb369506a2096811186015b33a80cf15b94.tar.gz
kernel-qcow2-util-linux-649efbb369506a2096811186015b33a80cf15b94.tar.xz
kernel-qcow2-util-linux-649efbb369506a2096811186015b33a80cf15b94.zip
login: login's timeout can fail
Login tries to set a timeout in main() by SIGALARM. If any restartable system call is entered, such system calls can block indefinitely and will NOT be interrupted by the SIGALRM. The bug appears when the login program is run for a terminal for which it doens't have read or write permission. In that case, login hung until manually killed by the administrator in its tcsetattr(...) call at login.c, line 460: /* Kill processes left on this tty */ tcsetattr(0,TCSAFLUSH,&ttt); This may possibly be a kernel bug - instead of returning EIO / EPERM, the kernel continously sends an infinite number of SIGTTOU signals to the process . An 80MB strace log file was generated, consisting of >1,000,000 repetitions of : 4964 11:00:18 ioctl(0, SNDCTL_TMR_CONTINUE or TCSETSF, {c_iflags=0x106, c_oflags=0x1805, c_cflags=0x800000be, c_lflags=0x3b, c_line=0, c_cc="\x03\x1c\x7f\x15\x04\x00\x01\x00\x11\x13\x1a\x00\x12\x0f\x17\x16\x00\x00\x00"}) = ? ERESTARTSYS (To be restarted) 4964 11:00:18 --- SIGTTOU (Stopped (tty output)) @ 0 (0) --- 4964 11:00:18 --- SIGTTOU (Stopped (tty output)) @ 0 (0) --- Login's alarm signal handler DOES get the SIGALRM after the 60 second timeout, and timedout() is called; but then timedout2 calls ioctl(0, TCSETA, &ti), which also blocks, because the ioctl(0, TCSETSF...) of tcsetattr is in progress, and the exit() call of timedout2 is never reached, and the tcsetattr call is restarted. From: Jason Vas Dias <jvdias@redhat.com> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'login-utils/login.c')
-rw-r--r--login-utils/login.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/login-utils/login.c b/login-utils/login.c
index 5895b8efa..ba3b86b09 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -342,6 +342,7 @@ main(int argc, char **argv)
pid = getpid();
signal(SIGALRM, timedout);
+ siginterrupt(SIGALRM,1); /* we have to interrupt syscalls like ioclt() */
alarm((unsigned int)timeout);
signal(SIGQUIT, SIG_IGN);
signal(SIGINT, SIG_IGN);