1. 14 1月, 2011 1 次提交
  2. 17 12月, 2010 4 次提交
  3. 30 11月, 2010 3 次提交
    • J
      TTY: open/hangup race fixup · acfa747b
      Jiri Slaby 提交于
      Like in the "TTY: don't allow reopen when ldisc is changing" patch,
      this one fixes a TTY WARNING as described in the option 1) there:
      1) __tty_hangup from tty_ldisc_hangup to tty_ldisc_enable. During this
      section tty_lock is held. However tty_lock is temporarily dropped in
      the middle of the function by tty_ldisc_hangup.
      
      The fix is to introduce a new flag which we set during the unlocked
      window and check it in tty_reopen too. The flag is TTY_HUPPING and is
      cleared after TTY_HUPPED is set.
      
      While at it, remove duplicate TTY_HUPPED set_bit. The one after
      calling ops->hangup seems to be more correct. But anyway, we hold
      tty_lock, so there should be no difference.
      
      Also document the function it does that kind of crap.
      
      Nicely reproducible with two forked children:
      static void do_work(const char *tty)
      {
      	if (signal(SIGHUP, SIG_IGN) == SIG_ERR) exit(1);
      	setsid();
      	while (1) {
      		int fd = open(tty, O_RDWR|O_NOCTTY);
      		if (fd < 0) continue;
      		if (ioctl(fd, TIOCSCTTY)) continue;
      		if (vhangup()) continue;
      		close(fd);
      	}
      	exit(0);
      }
      Signed-off-by: NJiri Slaby <jslaby@suse.cz>
      Reported-by: <Valdis.Kletnieks@vt.edu>
      Reported-by: NKyle McMartin <kyle@mcmartin.ca>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: stable <stable@kernel.org>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      acfa747b
    • J
      TTY: don't allow reopen when ldisc is changing · e2efafbf
      Jiri Slaby 提交于
      There are many WARNINGs like the following reported nowadays:
      WARNING: at drivers/tty/tty_io.c:1331 tty_open+0x2a2/0x49a()
      Hardware name: Latitude E6500
      Modules linked in:
      Pid: 1207, comm: plymouthd Not tainted 2.6.37-rc3-mmotm1123 #3
      Call Trace:
       [<ffffffff8103b189>] warn_slowpath_common+0x80/0x98
       [<ffffffff8103b1b6>] warn_slowpath_null+0x15/0x17
       [<ffffffff8128a3ab>] tty_open+0x2a2/0x49a
       [<ffffffff810fd53f>] chrdev_open+0x11d/0x146
      ...
      
      This means tty_reopen is called without TTY_LDISC set. For further
      considerations, note tty_lock is held in tty_open. TTY_LDISC is cleared in:
      1) __tty_hangup from tty_ldisc_hangup to tty_ldisc_enable. During this
      section tty_lock is held. However tty_lock is temporarily dropped in
      the middle of the function by tty_ldisc_hangup.
      
      2) tty_release via tty_ldisc_release till the end of tty existence. If
      tty->count <= 1, tty_lock is taken, TTY_CLOSING bit set and then
      tty_ldisc_release called. tty_reopen checks TTY_CLOSING before checking
      TTY_LDISC.
      
      3) tty_set_ldisc from tty_ldisc_halt to tty_ldisc_enable. We:
         * take tty_lock, set TTY_LDISC_CHANGING, put tty_lock
         * call tty_ldisc_halt (clear TTY_LDISC), tty_lock is _not_ held
         * do some other work
         * take tty_lock, call tty_ldisc_enable (set TTY_LDISC), put
           tty_lock
      
      I cannot see how 2) can be a problem, as there I see no race. OTOH, 1)
      and 3) can happen without problems. This patch the case 3) by checking
      TTY_LDISC_CHANGING along with TTY_CLOSING in tty_reopen. 1) will be
      fixed in the following patch.
      
      Nicely reproducible with two processes:
      while (1) {
      	fd = open("/dev/ttyS1", O_RDWR);
      	if (fd < 0) {
      		warn("open");
      		continue;
      	}
      	close(fd);
      }
      --------
      while (1) {
              fd = open("/dev/ttyS1", O_RDWR);
              ld1 = 0; ld2 = 2;
              while (1) {
                      ioctl(fd, TIOCSETD, &ld1);
                      ioctl(fd, TIOCSETD, &ld2);
              }
              close(fd);
      }
      Signed-off-by: NJiri Slaby <jslaby@suse.cz>
      Reported-by: <Valdis.Kletnieks@vt.edu>
      Cc: Kyle McMartin <kyle@mcmartin.ca>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: stable <stable@kernel.org>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      e2efafbf
    • J
      TTY: ldisc, fix open flag handling · 7f90cfc5
      Jiri Slaby 提交于
      When a concrete ldisc open fails in tty_ldisc_open, we forget to clear
      TTY_LDISC_OPEN. This causes a false warning on the next ldisc open:
      WARNING: at drivers/char/tty_ldisc.c:445 tty_ldisc_open+0x26/0x38()
      Hardware name: System Product Name
      Modules linked in: ...
      Pid: 5251, comm: a.out Tainted: G        W  2.6.32-5-686 #1
      Call Trace:
       [<c1030321>] ? warn_slowpath_common+0x5e/0x8a
       [<c1030357>] ? warn_slowpath_null+0xa/0xc
       [<c119311c>] ? tty_ldisc_open+0x26/0x38
       [<c11936c5>] ? tty_set_ldisc+0x218/0x304
      ...
      
      So clear the bit when failing...
      
      Introduced in c65c9bc3 (tty: rewrite the ldisc locking) back in
      2.6.31-rc1.
      Signed-off-by: NJiri Slaby <jslaby@suse.cz>
      Cc: Alan Cox <alan@linux.intel.com>
      Reported-by: NSergey Lapin <slapin@ossfans.org>
      Tested-by: NSergey Lapin <slapin@ossfans.org>
      Cc: stable <stable@kernel.org>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      7f90cfc5
  4. 12 11月, 2010 5 次提交
  5. 10 11月, 2010 3 次提交
    • P
      tty_ldisc: Fix BUG() on hangup · 1c95ba1e
      Philippe Rétornaz 提交于
      A kernel BUG when bluetooth rfcomm connection drop while the associated
      serial port is open is sometime triggered.
      
      It seems that the line discipline can disappear between the
      tty_ldisc_put and tty_ldisc_get. This patch fall back to the N_TTY line
      discipline if the previous discipline is not available anymore.
      Signed-off-by: NPhilippe Retornaz <philippe.retornaz@epfl.ch>
      Acked-by: NAlan Cox <alan@linux.intel.com>
      Cc: stable <stable@kernel.org>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      1c95ba1e
    • 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
  6. 06 11月, 2010 1 次提交
  7. 05 11月, 2010 2 次提交