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)
committerBen Hutchings <ben@decadent.org.uk>
Wed, 6 Mar 2013 03:23:49 +0000 (03:23 +0000)
commit 183d95cdd834381c594d3aa801c1f9f9c0c54fa9 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
drivers/tty/tty_ioctl.c

index 9314d93..937f927 100644 (file)
@@ -618,7 +618,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);
@@ -685,7 +685,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);