1. 24 7月, 2013 10 次提交
  2. 10 4月, 2013 1 次提交
    • P
      tty: Fix race condition if flushing tty flip buffers · 39f610e4
      Peter Hurley 提交于
      As Ilya Zykov identified in his patch 'PROBLEM: Race condition in
      tty buffer's function flush_to_ldisc()', a race condition exists
      which allows a parallel flush_to_ldisc() to flush and free the tty
      flip buffers while those buffers are in-use. For example,
      
        CPU 0                         |  CPU 1                                  |  CPU 2
                                      | flush_to_ldisc()                        |
                                      |  grab spin lock                         |
      tty_buffer_flush()              |                                         | flush_to_ldisc()
       wait for spin lock             |                                         |  wait for spin lock
                                      |   if (!test_and_set_bit(TTYP_FLUSHING)) |
                                      |    while (next flip buffer)             |
                                      |     ...                                 |
                                      |     drop spin lock                      |
        grab spin lock                |                                         |
         if (test_bit(TTYP_FLUSHING)) |                                         |
          set_bit(TTYP_FLUSHPENDING)  |      receive_buf()                      |
          drop spin lock              |                                         |
                                      |                                         |   grab spin lock
                                      |                                         |    if (!test_and_set_bit(TTYP_FLUSHING))
                                      |                                         |    if (test_bit(TTYP_FLUSHPENDING))
                                      |                                         |    __tty_buffer_flush()
      
      CPU 2 has just flushed and freed all tty flip buffers while CPU 1 is
      transferring data from the head flip buffer.
      
      The original patch was rejected under the assumption that parallel
      flush_to_ldisc() was not possible. Because of necessary changes to
      the workqueue api, work items can execute in parallel on SMP.
      
      This patch differs slightly from the original patch by testing for
      a pending flush _after_ each receive_buf(), since TTYP_FLUSHPENDING
      can only be set while the lock is dropped around receive_buf().
      Reported-by: NIlya Zykov <linux@izyk.ru>
      Signed-off-by: NPeter Hurley <peter@hurleysoftware.com>
      Acked-by: NIlya Zykov <linux@izyk.ru>
      Cc: Jiri Slaby <jslaby@suse.cz>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      39f610e4
  3. 04 3月, 2013 1 次提交
  4. 14 2月, 2013 1 次提交
    • G
      pps: Move timestamp read into PPS code proper · 593fb1ae
      George Spelvin 提交于
      The PPS (Pulse-Per-Second) line discipline has developed a number of
      unhealthy attachments to core tty data and functions, ultimately leading
      to its breakage.
      
      The previous patches fixed the crashing.  This one reduces coupling further
      by eliminating the timestamp parameter from the dcd_change ldisc method.
      This reduces header file linkage and makes the extension more generic,
      and the timestamp read is delayed only slightly, from just before the
      ldisc->ops->dcd_change method call to just after.
      
      Fix attendant build breakage in
          drivers/tty/n_tty.c
          drivers/tty/tty_buffer.c
          drivers/staging/speakup/selection.c
          drivers/staging/dgrp/dgrp_*.c
      
      Cc: William Hubbs <w.d.hubbs@gmail.com>
      Cc: Chris Brannon <chris@the-brannons.com>
      Cc: Kirk Reiser <kirk@braille.uwo.ca>
      Cc: Samuel Thibault <samuel.thibault@ens-lyon.org>
      Signed-off-by: NPeter Hurley <peter@hurleysoftware.com>
      Signed-off-by: NGeorge Spelvin <linux@horizon.com>
      Acked-by: NRodolfo Giometti <giometti@enneenne.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      593fb1ae
  5. 21 1月, 2013 1 次提交
    • I
      tty: Correct tty buffer flush. · 64325a3b
      Ilya Zykov 提交于
        The root of problem is carelessly zeroing pointer(in function __tty_buffer_flush()),
      when another thread can use it. It can be cause of "NULL pointer dereference".
        Main idea of the patch, this is never free last (struct tty_buffer) in the active buffer.
      Only flush the data for ldisc(buf->head->read = buf->head->commit).
      At that moment driver can collect(write) data in buffer without conflict.
      It is repeat behavior of flush_to_ldisc(), only without feeding data to ldisc.
      
      Also revert:
        commit c56a00a1
        tty: hold lock across tty buffer finding and buffer filling
      In order to delete the unneeded locks any more.
      Signed-off-by: NIlya Zykov <ilya@ilyx.ru>
      CC: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      64325a3b
  6. 16 1月, 2013 5 次提交
  7. 26 10月, 2012 1 次提交
  8. 25 10月, 2012 1 次提交
  9. 23 10月, 2012 4 次提交
  10. 10 4月, 2012 1 次提交
  11. 08 6月, 2011 1 次提交
    • L
      tty_buffer: get rid of 'seen_tail' logic in flush_to_ldisc · 81de916f
      Linus Torvalds 提交于
      The flush_to_ldisc() work entry has special logic to notice when it has
      seen the original tail of the data queue, and it avoids continuing the
      flush if it sees that _original_ tail rather than the current tail.
      
      This logic can trigger in case somebody is constantly adding new data to
      the tty while the flushing is active - and the intent is to avoid
      excessive CPU usage while flushing the tty, especially as we used to do
      this from a softirq context which made it non-preemptible.
      
      However, since we no longer re-arm the work-queue from within itself
      (because that causes other trouble: see commit a5660b41 "tty: fix
      endless work loop when the buffer fills up"), this just leads to
      possible hung tty's (most easily seen in SMP and with a test-program
      that floods a pty with data - nobody seems to have reported this for any
      real-life situation yet).
      
      And since the workqueue isn't done from timers and softirq's any more,
      it's doubtful whether the CPU useage issue is really relevant any more.
      So just remove the logic entirely, and see if anybody ever notices.
      
      Alternatively, we might want to re-introduce the "re-arm the work" for
      just this case, but then we'd have to re-introduce the delayed work
      model or some explicit timer, which really doesn't seem worth it for
      this.
      Reported-and-tested-by: NGuillaume Chazarain <guichaz@gmail.com>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: Felipe Balbi <balbi@ti.com>
      Cc: Greg Kroah-Hartman <gregkh@suse.de>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      81de916f
  12. 04 6月, 2011 1 次提交
    • L
      Revert "tty: make receive_buf() return the amout of bytes received" · 55db4c64
      Linus Torvalds 提交于
      This reverts commit b1c43f82.
      
      It was broken in so many ways, and results in random odd pty issues.
      
      It re-introduced the buggy schedule_work() in flush_to_ldisc() that can
      cause endless work-loops (see commit a5660b41: "tty: fix endless
      work loop when the buffer fills up").
      
      It also used an "unsigned int" return value fo the ->receive_buf()
      function, but then made multiple functions return a negative error code,
      and didn't actually check for the error in the caller.
      
      And it didn't actually work at all.  BenH bisected down odd tty behavior
      to it:
        "It looks like the patch is causing some major malfunctions of the X
         server for me, possibly related to PTYs.  For example, cat'ing a
         large file in a gnome terminal hangs the kernel for -minutes- in a
         loop of what looks like flush_to_ldisc/workqueue code, (some ftrace
         data in the quoted bits further down).
      
         ...
      
         Some more data: It -looks- like what happens is that the
         flush_to_ldisc work queue entry constantly re-queues itself (because
         the PTY is full ?) and the workqueue thread will basically loop
         forver calling it without ever scheduling, thus starving the consumer
         process that could have emptied the PTY."
      
      which is pretty much exactly the problem we fixed in a5660b41.
      
      Milton Miller pointed out the 'unsigned int' issue.
      Reported-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
      Reported-by: NMilton Miller <miltonm@bga.com>
      Cc: Stefan Bigler <stefan.bigler@keymile.com>
      Cc: Toby Gray <toby.gray@realvnc.com>
      Cc: Felipe Balbi <balbi@ti.com>
      Cc: Greg Kroah-Hartman <gregkh@suse.de>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      55db4c64
  13. 23 4月, 2011 1 次提交
  14. 05 4月, 2011 1 次提交
    • L
      tty: fix endless work loop when the buffer fills up · a5660b41
      Linus Torvalds 提交于
      Commit f23eb2b2 ('tty: stop using "delayed_work" in the tty layer')
      ended up causing hung machines on UP with no preemption, because the
      work routine to flip the buffer data to the ldisc would endlessly re-arm
      itself if the destination buffer had filled up.
      
      With the delayed work, that only caused a timer-driving polling of the
      tty state every timer tick, but without the delay we just ended up with
      basically a busy loop instead.
      
      Stop the insane polling, and instead make the code that opens up the
      receive room re-schedule the buffer flip work.  That's what we should
      have been doing anyway.
      
      This same "poll for tty room" issue is almost certainly also the cause
      of excessive kworker activity when idle reported by Dave Jones, who also
      reported "flush_to_ldisc executing 2500 times a second" back in Nov 2010:
      
        http://lkml.org/lkml/2010/11/30/592
      
      which is that silly flushing done every timer tick.  Wasting both power
      and CPU for no good reason.
      Reported-and-tested-by: NAlexander Beregalov <a.beregalov@gmail.com>
      Reported-and-tested-by: NSitsofe Wheeler <sitsofe@yahoo.com>
      Cc: Greg KH <gregkh@suse.de>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: Dave Jones <davej@redhat.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      a5660b41
  15. 23 3月, 2011 1 次提交
    • L
      tty: stop using "delayed_work" in the tty layer · f23eb2b2
      Linus Torvalds 提交于
      Using delayed-work for tty flip buffers ends up causing us to wait for
      the next tick to complete some actions.  That's usually not all that
      noticeable, but for certain latency-critical workloads it ends up being
      totally unacceptable.
      
      As an extreme case of this, passing a token back-and-forth over a pty
      will take two ticks per iteration, so even just a thousand iterations
      will take 8 seconds assuming a common 250Hz configuration.
      
      Avoiding the whole delayed work issue brings that ping-pong test-case
      down to 0.009s on my machine.
      
      In more practical terms, this latency has been a performance problem for
      things like dive computer simulators (simulating the serial interface
      using the ptys) and for other environments (Alan mentions a CP/M emulator).
      Reported-by: NJef Driesen <jefdriesen@telenet.be>
      Acked-by: NGreg KH <gregkh@suse.de>
      Acked-by: NAlan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      f23eb2b2
  16. 10 11月, 2010 1 次提交
    • 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
  17. 05 11月, 2010 1 次提交
  18. 22 5月, 2010 1 次提交
  19. 19 3月, 2010 1 次提交
    • F
      tty_buffer: Fix distinct type warning · d4bee0a6
      Fang Wenqi 提交于
      CC      drivers/char/tty_buffer.o
      drivers/char/tty_buffer.c: In function ‘tty_insert_flip_string_fixed_flag’:
      drivers/char/tty_buffer.c:251: warning: comparison of distinct pointer types lacks a cast
      drivers/char/tty_buffer.c: In function ‘tty_insert_flip_string_flags’:
      drivers/char/tty_buffer.c:288: warning: comparison of distinct pointer types lacks a cast
      
      Fix it by replacing min() with min_t() in tty_insert_flip_string_flags and
      					  tty_insert_flip_string_fixed_flag().
      Signed-off-by: NFang Wenqi <antonf@turbolinux.com.cn>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      d4bee0a6
  20. 03 3月, 2010 2 次提交
  21. 15 10月, 2009 3 次提交
    • L
      tty: use the new 'flush_delayed_work()' helper to do ldisc flush · 97ad5a03
      Linus Torvalds 提交于
      This way all flush_to_ldisc work is always done through the workqueues,
      and we thus have a single point of serialization.  It also means that we
      can avoid calling flush_to_ldisc() entirely if there was no delayed work
      pending.
      
      [ Side note: using workqueues and keventd as the single way to enter
        flush_to_ldisc() still doesn't absolutely guarantee that we can't have
        concurrency: keventd is multithreaded and has a thread per CPU, and
        while the WORK_STRUCT_PENDING bit guarantees a single work only being
        on the pending list once, the work might be both pending and _running_
        at the same time. Workqueues are not simple. ]
      
      This was also confirmed to fix bugzilla #14388, even without the earlier
      locking fix and cleanup (commit c8e33141: "tty: Make flush_to_ldisc()
      locking more robust").  So both commits fix the same bug differently,
      and either would have worked on its own.  But I'm committing them both
      since they are cleanups independent of each other.
      Reported-and-tested-by: NBoyan <btanastasov@yahoo.co.uk>
      Acked-by: NAlan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      97ad5a03
    • L
      tty: Make flush_to_ldisc() locking more robust · c8e33141
      Linus Torvalds 提交于
      The locking logic in this function is extremely subtle, and it broke
      when we started doing potentially concurrent 'flush_to_ldisc()' calls in
      commit e043e42b ("pty: avoid forcing
      'low_latency' tty flag").
      
      The code in flush_to_ldisc() used to set 'tty->buf.head' to NULL, with
      the intention that this would then cause any other concurrent calls to
      not do anything (locking note: we have to drop the buf.lock over the
      call to ->receive_buf that can block, which is why we can have
      concurrency here at all in the first place).
      
      It also used to set the TTY_FLUSHING bit, which would then cause any
      concurrent 'tty_buffer_flush()' to not free all the tty buffers and
      clear 'tty->buf.tail'.  And with 'buf.head' being NULL, and 'buf.tail'
      being non-NULL, new data would never touch 'buf.head'.
      
      Does that sound a bit too subtle? It was.  If another concurrent call to
      'flush_to_ldisc()' were to come in, the NULL buf.head would indeed cause
      it to not process the buffer list, but it would still clear TTY_FLUSHING
      afterwards, making the buffer protection against 'tty_buffer_flush()' no
      longer work.
      
      So this clears it all up.  We depend purely on TTY_FLUSHING for handling
      re-entrancy, and stop playing games with the buffer list entirely.  In
      fact, the buffer list handling is now robust enough that we could
      probably stop doing the whole "protect against 'tty_buffer_flush()'"
      thing entirely.
      
      However, Alan also points out that we would probably be better off
      simplifying the locking even further, and just take the tty ldisc_mutex
      around all the buffer flushing calls.  That seems like a good idea, but
      in the meantime this is a conceptually minimal fix (with the patch
      itself being bigger than required just to clean the code up and make it
      readable).
      
      This fixes keyboard trouble under X:
      
      	http://bugzilla.kernel.org/show_bug.cgi?id=14388Reported-and-tested-by: NFrédéric Meunier <fredlwm@gmail.com>
      Reported-and-tested-by: NBoyan <btanastasov@yahoo.co.uk>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: Paul Fulghum <paulkf@microgate.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      c8e33141
    • L
      tty: use the new 'flush_delayed_work()' helper to do ldisc flush · 514fc01d
      Linus Torvalds 提交于
      This way all flush_to_ldisc work is always done through the workqueues,
      and we thus have a single point of serialization.
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      514fc01d