1. 10 11月, 2010 2 次提交
    • J
      TTY: restore tty_ldisc_wait_idle · 100eeae2
      Jiri Slaby 提交于
      It was removed in 65b77046 (tty-ldisc: turn ldisc user count into
      a proper refcount), but we need to wait for last user to quit the
      ldisc before we close it in tty_set_ldisc.
      
      Otherwise weird things start to happen. There might be processes
      waiting in tty_read->n_tty_read on tty->read_wait for input to appear
      and at that moment, a change of ldisc is fatal. n_tty_close is called,
      it frees read_buf and the waiting process is still in the middle of
      reading and goes nuts after it is woken.
      
      Previously we prevented close to happen when others are in ldisc ops
      by tty_ldisc_wait_idle in tty_set_ldisc. But the commit above removed
      that. So revoke the change and test whether there is 1 user (=we), and
      allow the close then.
      
      We can do that without ldisc/tty locks, because nobody else can open
      the device due to TTY_LDISC_CHANGING bit set, so we in fact wait for
      everybody to leave.
      
      I don't understand why tty_ldisc_lock would be needed either when the
      counter is an atomic variable, so this is a lockless
      tty_ldisc_wait_idle.
      
      On the other hand, if we fail to wait (timeout or signal), we have to
      reenable the halted ldiscs, so we take ldisc lock and reuse the setup
      path at the end of tty_set_ldisc.
      Signed-off-by: NJiri Slaby <jslaby@suse.cz>
      Acked-by: NLinus Torvalds <torvalds@linux-foundation.org>
      Tested-by: NSebastian Andrzej Siewior <bigeasy@breakpoint.cc>
      LKML-Reference: <20101031104136.GA511@Chamillionaire.breakpoint.cc>
      LKML-Reference: <1287669539-22644-1-git-send-email-jslaby@suse.cz>
      Cc: Alan Cox <alan@linux.intel.com>
      Cc: stable@kernel.org [32, 33, 36]
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      100eeae2
    • J
      tty: prevent DOS in the flush_to_ldisc · e045fec4
      Jiri Olsa 提交于
      There's a small window inside the flush_to_ldisc function,
      where the tty is unlocked and calling ldisc's receive_buf
      function. If in this window new buffer is added to the tty,
      the processing might never leave the flush_to_ldisc function.
      
      This scenario will hog the cpu, causing other tty processing
      starving, and making it impossible to interface the computer
      via tty.
      
      I was able to exploit this via pty interface by sending only
      control characters to the master input, causing the flush_to_ldisc
      to be scheduled, but never actually generate any output.
      
      To reproduce, please run multiple instances of following code.
      
      - SNIP
      #define _XOPEN_SOURCE
      #include <stdlib.h>
      #include <stdio.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      
      int main(int argc, char **argv)
      {
              int i, slave, master = getpt();
              char buf[8192];
      
              sprintf(buf, "%s", ptsname(master));
              grantpt(master);
              unlockpt(master);
      
              slave = open(buf, O_RDWR);
              if (slave < 0) {
                      perror("open slave failed");
                      return 1;
              }
      
              for(i = 0; i < sizeof(buf); i++)
                      buf[i] = rand() % 32;
      
              while(1) {
                      write(master, buf, sizeof(buf));
              }
      
              return 0;
      }
      - SNIP
      
      The attached patch (based on -next tree) fixes this by checking on the
      tty buffer tail. Once it's reached, the current work is rescheduled
      and another could run.
      Signed-off-by: NJiri Olsa <jolsa@redhat.com>
      Cc: stable <stable@kernel.org>
      Acked-by: NAlan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      e045fec4
  2. 06 11月, 2010 1 次提交
  3. 05 11月, 2010 2 次提交