diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-01-29 20:07:41 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-05 00:02:14 +0100 |
commit | 183d95cdd834381c594d3aa801c1f9f9c0c54fa9 (patch) | |
tree | 8b24e0721242433a757f874f68ae21cf69acbb0d /drivers/tty/tty_ioctl.c | |
parent | tty: Prevent deadlock in n_gsm driver (diff) | |
download | linux-183d95cdd834381c594d3aa801c1f9f9c0c54fa9.tar.xz linux-183d95cdd834381c594d3aa801c1f9f9c0c54fa9.zip |
tty: set_termios/set_termiox should not return -EINTR
See https://bugzilla.redhat.com/show_bug.cgi?id=904907
read command causes bash to abort with double free or corruption (out).
A simple test-case from Roman:
// Compile the reproducer and send sigchld ti that process.
// EINTR occurs even if SA_RESTART flag is set.
void handler(int sig)
{
}
main()
{
struct sigaction act;
act.sa_handler = handler;
act.sa_flags = SA_RESTART;
sigaction (SIGCHLD, &act, 0);
struct termio ttp;
ioctl(0, TCGETA, &ttp);
while(1)
{
if (ioctl(0, TCSETAW, ttp) < 0)
{
if (errno == EINTR)
{
fprintf(stderr, "BUG!"); return(1);
}
}
}
}
Change set_termios/set_termiox to return -ERESTARTSYS to fix this
particular problem.
I didn't dare to change other EINTR's in drivers/tty/, but they look
equally wrong.
Reported-by: Roman Rakus <rrakus@redhat.com>
Reported-by: Lingzhu Xiang <lxiang@redhat.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_ioctl.c')
-rw-r--r-- | drivers/tty/tty_ioctl.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index cc0fc52787c7..d58b92cc187c 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -617,7 +617,7 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) - return -EINTR; + return -ERESTARTSYS; } tty_set_termios(tty, &tmp_termios); @@ -684,7 +684,7 @@ static int set_termiox(struct tty_struct *tty, void __user *arg, int opt) if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) - return -EINTR; + return -ERESTARTSYS; } mutex_lock(&tty->termios_mutex); |