]>
Commit | Line | Data |
---|---|---|
2bbc3dc8 GKH |
1 | From 79fbf4a550ed6a22e1ae1516113e6c7fa5d56a53 Mon Sep 17 00:00:00 2001 |
2 | From: Johan Hovold <johan@kernel.org> | |
3 | Date: Wed, 4 Mar 2015 10:39:06 +0100 | |
4 | Subject: TTY: fix tty_wait_until_sent on 64-bit machines | |
5 | ||
6 | From: Johan Hovold <johan@kernel.org> | |
7 | ||
8 | commit 79fbf4a550ed6a22e1ae1516113e6c7fa5d56a53 upstream. | |
9 | ||
10 | Fix overflow bug in tty_wait_until_sent on 64-bit machines, where an | |
11 | infinite timeout (0) would be passed to the underlying tty-driver's | |
12 | wait_until_sent-operation as a negative timeout (-1), causing it to | |
13 | return immediately. | |
14 | ||
15 | This manifests itself for example as tcdrain() returning immediately, | |
16 | drivers not honouring the drain flags when setting terminal attributes, | |
17 | or even dropped data on close as a requested infinite closing-wait | |
18 | timeout would be ignored. | |
19 | ||
20 | The first symptom was reported by Asier LLANO who noted that tcdrain() | |
21 | returned prematurely when using the ftdi_sio usb-serial driver. | |
22 | ||
23 | Fix this by passing 0 rather than MAX_SCHEDULE_TIMEOUT (LONG_MAX) to the | |
24 | underlying tty driver. | |
25 | ||
26 | Note that the serial-core wait_until_sent-implementation is not affected | |
27 | by this bug due to a lucky chance (comparison to an unsigned maximum | |
28 | timeout), and neither is the cyclades one that had an explicit check for | |
29 | negative timeouts, but all other tty drivers appear to be affected. | |
30 | ||
31 | Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") | |
32 | Reported-by: ZIV-Asier Llano Palacios <asier.llano@cgglobal.com> | |
33 | Signed-off-by: Johan Hovold <johan@kernel.org> | |
34 | Reviewed-by: Peter Hurley <peter@hurleysoftware.com> | |
35 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
36 | ||
37 | --- | |
38 | drivers/tty/tty_ioctl.c | 12 +++++++++--- | |
39 | 1 file changed, 9 insertions(+), 3 deletions(-) | |
40 | ||
41 | --- a/drivers/tty/tty_ioctl.c | |
42 | +++ b/drivers/tty/tty_ioctl.c | |
43 | @@ -217,11 +217,17 @@ void tty_wait_until_sent(struct tty_stru | |
44 | #endif | |
45 | if (!timeout) | |
46 | timeout = MAX_SCHEDULE_TIMEOUT; | |
47 | + | |
48 | if (wait_event_interruptible_timeout(tty->write_wait, | |
49 | - !tty_chars_in_buffer(tty), timeout) >= 0) { | |
50 | - if (tty->ops->wait_until_sent) | |
51 | - tty->ops->wait_until_sent(tty, timeout); | |
52 | + !tty_chars_in_buffer(tty), timeout) < 0) { | |
53 | + return; | |
54 | } | |
55 | + | |
56 | + if (timeout == MAX_SCHEDULE_TIMEOUT) | |
57 | + timeout = 0; | |
58 | + | |
59 | + if (tty->ops->wait_until_sent) | |
60 | + tty->ops->wait_until_sent(tty, timeout); | |
61 | } | |
62 | EXPORT_SYMBOL(tty_wait_until_sent); | |
63 |