From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: stable-review@kernel.org, torvalds@linux-foundation.org,
akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk,
Paul Fulghum <paulkf@microgate.com>,
Greg Kroah-Hartman <gregkh@suse.de>
Subject: [46/46] tty: Make flush_to_ldisc() locking more robust
Date: Fri, 16 Oct 2009 10:10:39 -0700 [thread overview]
Message-ID: <20091016171210.987917756@linux.site> (raw)
In-Reply-To: <20091016171422.GA13339@kroah.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: tty-make-flush_to_ldisc-locking-more-robust.patch --]
[-- Type: text/plain, Size: 4345 bytes --]
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Linus Torvalds <torvalds@linux-foundation.org>
commit c8e33141911bf8fe87dc6c92793b9a59b2be0130 upstream.
The locking logic in this function is extremely subtle, and it broke
when we started doing potentially concurrent 'flush_to_ldisc()' calls in
commit e043e42bdb66885b3ac10d27a01ccb9972e2b0a3 ("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=14388
Reported-and-tested-by: Frédéric Meunier <fredlwm@gmail.com>
Reported-and-tested-by: Boyan <btanastasov@yahoo.co.uk>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Paul Fulghum <paulkf@microgate.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/char/tty_buffer.c | 29 +++++++++++++----------------
1 file changed, 13 insertions(+), 16 deletions(-)
--- a/drivers/char/tty_buffer.c
+++ b/drivers/char/tty_buffer.c
@@ -402,28 +402,26 @@ static void flush_to_ldisc(struct work_s
container_of(work, struct tty_struct, buf.work.work);
unsigned long flags;
struct tty_ldisc *disc;
- struct tty_buffer *tbuf, *head;
- char *char_buf;
- unsigned char *flag_buf;
disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
return;
spin_lock_irqsave(&tty->buf.lock, flags);
- /* So we know a flush is running */
- set_bit(TTY_FLUSHING, &tty->flags);
- head = tty->buf.head;
- if (head != NULL) {
- tty->buf.head = NULL;
- for (;;) {
- int count = head->commit - head->read;
+
+ if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
+ struct tty_buffer *head;
+ while ((head = tty->buf.head) != NULL) {
+ int count;
+ char *char_buf;
+ unsigned char *flag_buf;
+
+ count = head->commit - head->read;
if (!count) {
if (head->next == NULL)
break;
- tbuf = head;
- head = head->next;
- tty_buffer_free(tty, tbuf);
+ tty->buf.head = head->next;
+ tty_buffer_free(tty, head);
continue;
}
/* Ldisc or user is trying to flush the buffers
@@ -445,9 +443,9 @@ static void flush_to_ldisc(struct work_s
flag_buf, count);
spin_lock_irqsave(&tty->buf.lock, flags);
}
- /* Restore the queue head */
- tty->buf.head = head;
+ clear_bit(TTY_FLUSHING, &tty->flags);
}
+
/* We may have a deferred request to flush the input buffer,
if so pull the chain under the lock and empty the queue */
if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
@@ -455,7 +453,6 @@ static void flush_to_ldisc(struct work_s
clear_bit(TTY_FLUSHPENDING, &tty->flags);
wake_up(&tty->read_wait);
}
- clear_bit(TTY_FLUSHING, &tty->flags);
spin_unlock_irqrestore(&tty->buf.lock, flags);
tty_ldisc_deref(disc);
next prev parent reply other threads:[~2009-10-16 17:18 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20091016170953.128828149@linux.site>
2009-10-16 17:14 ` [00/46] 2.6.31.5-stable review Greg KH
2009-10-16 17:09 ` [01/46] SCSI: Retry ADD_TO_MLQUEUE return value for EH commands Greg KH
2009-10-16 17:09 ` [02/46] SCSI: Fix protection scsi_data_buffer leak Greg KH
2009-10-16 17:09 ` [03/46] SCSI: sg: Free data buffers after calling blk_rq_unmap_user Greg KH
2009-10-16 17:09 ` [04/46] ARM: pxa: workaround errata #37 by not using half turbo switching Greg KH
2009-10-16 17:09 ` [05/46] tracing/filters: Fix memory leak when setting a filter Greg KH
2009-10-16 17:09 ` [06/46] x86/paravirt: Use normal calling sequences for irq enable/disable Greg KH
2009-10-16 17:09 ` Greg KH
2009-10-16 17:10 ` [07/46] USB: ftdi_sio: remove tty->low_latency Greg KH
2009-10-16 17:10 ` [08/46] USB: ftdi_sio: remove unused rx_byte counter Greg KH
2009-10-16 17:10 ` [09/46] USB: ftdi_sio: clean up read completion handler Greg KH
2009-10-16 17:10 ` [10/46] USB: ftdi_sio: re-implement read processing Greg KH
2009-10-16 17:10 ` [11/46] USB: pl2303: fix error characters not being reported to ldisc Greg KH
2009-10-16 17:10 ` [12/46] USB: digi_acceleport: Fix broken unthrottle Greg KH
2009-10-16 17:10 ` [13/46] USB: serial: dont call release without attach Greg KH
2009-10-16 17:10 ` [14/46] USB: option: Toshiba G450 device id Greg KH
2009-10-16 17:10 ` [15/46] USB: ipaq: fix oops when device is plugged in Greg KH
2009-10-16 17:10 ` [16/46] USB: cp210x: Add support for the DW700 UART Greg KH
2009-10-16 17:10 ` [17/46] USB: Fix throttling in generic usbserial driver Greg KH
2009-10-16 17:10 ` [18/46] USB: storage: When a device returns no sense data, call it a Hardware Error Greg KH
2009-10-16 17:10 ` [19/46] arm, cris, mips, sparc, powerpc, um, xtensa: fix build with bash 4.0 Greg KH
2009-10-16 17:10 ` [20/46] intel-iommu: Cope with broken HP DC7900 BIOS Greg KH
2009-10-16 17:10 ` [21/46] futex: Detect mismatched requeue targets Greg KH
2009-10-16 17:10 ` [22/46] futex: Fix wakeup race by setting TASK_INTERRUPTIBLE before queue_me() Greg KH
2009-10-16 17:10 ` [23/46] tpm-fixup-pcrs-sysfs-file-update Greg KH
2009-10-16 17:10 ` [24/46] TPM: fix pcrread Greg KH
2009-10-16 17:10 ` [25/46] Bluetooth: Disconnect HIDRAW devices on disconnect Greg KH
2009-10-16 17:10 ` [26/46] Bluetooth: Add extra device reference counting for connections Greg KH
2009-10-16 17:10 ` [27/46] Bluetooth: Let HIDP grab the device reference " Greg KH
2009-10-16 17:10 ` [28/46] connector: Keep the skb in cn_callback_data Greg KH
2009-10-16 17:10 ` [29/46] connector: Provide the senders credentials to the callback Greg KH
2009-10-16 17:10 ` [30/46] connector: Removed the destruct_data callback since it is always kfree_skb() Greg KH
2009-10-16 17:10 ` [31/46] dm/connector: Only process connector packages from privileged processes Greg KH
2009-10-16 17:10 ` [32/46] dst/connector: Disallow unpliviged users to configure dst Greg KH
2009-10-16 17:10 ` [33/46] pohmelfs/connector: Disallow unpliviged users to configure pohmelfs Greg KH
2009-10-16 17:10 ` [34/46] uvesafb/connector: Disallow unpliviged users to send netlink packets Greg KH
2009-10-16 17:10 ` [35/46] e1000e: swap max hw supported frame size between 82574 and 82583 Greg KH
2009-10-16 17:10 ` [36/46] MAINTAINERS: Fix Riku Voipios address Greg KH
2009-10-16 17:10 ` [37/46] macintosh: Dont assume i2c device probing always succeeds Greg KH
2009-10-16 17:10 ` [38/46] i2c: Hide probe errors caused by ACPI resource conflicts Greg KH
2009-10-16 17:10 ` [39/46] ALSA: Dont assume i2c device probing always succeeds Greg KH
2009-10-16 17:10 ` [40/46] bsdacct: switch credentials for writing to the accounting file Greg KH
2009-10-16 17:10 ` [41/46] sysfs: Allow sysfs_notify_dirent to be called from interrupt context Greg KH
2009-10-16 17:10 ` [42/46] Staging: rt2860sta: prevent a panic when disabling when associated Greg KH
2009-10-16 17:10 ` [43/46] usb-storage: Workaround devices with bogus sense size Greg KH
2009-10-16 17:10 ` [44/46] iwlwifi: incorrect method used for finding valid OTP blocks Greg KH
2009-10-16 17:10 ` [45/46] mac80211: fix vlan and optimise RX Greg KH
2009-10-16 17:10 ` Greg KH [this message]
2009-10-16 17:57 ` [00/46] 2.6.31.5-stable review Massimo Cetra
2009-10-16 18:03 ` Greg KH
2009-10-17 5:20 ` Massimo Cetra
2009-11-05 23:12 ` Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20091016171210.987917756@linux.site \
--to=gregkh@suse.de \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=linux-kernel@vger.kernel.org \
--cc=paulkf@microgate.com \
--cc=stable-review@kernel.org \
--cc=stable@kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.