diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-01-29 14:07:41 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-04 18:02:14 -0500 |
commit | 183d95cdd834381c594d3aa801c1f9f9c0c54fa9 (patch) | |
tree | 8b24e0721242433a757f874f68ae21cf69acbb0d /drivers/tty/tty_ioctl.c | |
parent | 4d9b109060f690f5c835130ff54165ae157b3087 (diff) |
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) | |||
617 | if (opt & TERMIOS_WAIT) { | 617 | if (opt & TERMIOS_WAIT) { |
618 | tty_wait_until_sent(tty, 0); | 618 | tty_wait_until_sent(tty, 0); |
619 | if (signal_pending(current)) | 619 | if (signal_pending(current)) |
620 | return -EINTR; | 620 | return -ERESTARTSYS; |
621 | } | 621 | } |
622 | 622 | ||
623 | tty_set_termios(tty, &tmp_termios); | 623 | tty_set_termios(tty, &tmp_termios); |
@@ -684,7 +684,7 @@ static int set_termiox(struct tty_struct *tty, void __user *arg, int opt) | |||
684 | if (opt & TERMIOS_WAIT) { | 684 | if (opt & TERMIOS_WAIT) { |
685 | tty_wait_until_sent(tty, 0); | 685 | tty_wait_until_sent(tty, 0); |
686 | if (signal_pending(current)) | 686 | if (signal_pending(current)) |
687 | return -EINTR; | 687 | return -ERESTARTSYS; |
688 | } | 688 | } |
689 | 689 | ||
690 | mutex_lock(&tty->termios_mutex); | 690 | mutex_lock(&tty->termios_mutex); |