tty: set_termios/set_termiox should not return -EINTR
authorOleg Nesterov <oleg@redhat.com>
Tue, 29 Jan 2013 19:07:41 +0000 (20:07 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Feb 2013 23:02:14 +0000 (15:02 -0800)
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>
drivers/tty/tty_ioctl.c

index cc0fc52787c74ea41f7a36afb74138ef1e85613f..d58b92cc187cc21b05229ee9cdd7e936519fffb8 100644 (file)
@@ -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);