]> git.proxmox.com Git - pve-kernel-3.10.0.git/blame - n_tty-Fix-n_tty_write-crash-when-echoing-in-raw-mode.patch
enable vfio-vga
[pve-kernel-3.10.0.git] / n_tty-Fix-n_tty_write-crash-when-echoing-in-raw-mode.patch
CommitLineData
3c6eeea3
DM
1From: Peter Hurley <peter@hurleysoftware.com>\r
2\r
3commit 4291086b1f081b869c6d79e5b7441633dc3ace00 upstream.\r
4\r
5The tty atomic_write_lock does not provide an exclusion guarantee for\r
6the tty driver if the termios settings are LECHO & !OPOST. And since\r
7it is unexpected and not allowed to call TTY buffer helpers like\r
8tty_insert_flip_string concurrently, this may lead to crashes when\r
9concurrect writers call pty_write. In that case the following two\r
10writers:\r
11* the ECHOing from a workqueue and\r
12* pty_write from the process\r
13race and can overflow the corresponding TTY buffer like follows.\r
14\r
15If we look into tty_insert_flip_string_fixed_flag, there is:\r
16 int space = __tty_buffer_request_room(port, goal, flags);\r
17 struct tty_buffer *tb = port->buf.tail;\r
18 ...\r
19 memcpy(char_buf_ptr(tb, tb->used), chars, space);\r
20 ...\r
21 tb->used += space;\r
22\r
23so the race of the two can result in something like this:\r
24 A B\r
25__tty_buffer_request_room\r
26 __tty_buffer_request_room\r
27memcpy(buf(tb->used), ...)\r
28tb->used += space;\r
29 memcpy(buf(tb->used), ...) ->BOOM\r
30\r
31B's memcpy is past the tty_buffer due to the previous A's tb->used\r
32increment.\r
33\r
34Since the N_TTY line discipline input processing can output\r
35concurrently with a tty write, obtain the N_TTY ldisc output_lock to\r
36serialize echo output with normal tty writes. This ensures the tty\r
37buffer helper tty_insert_flip_string is not called concurrently and\r
38everything is fine.\r
39\r
40Note that this is nicely reproducible by an ordinary user using\r
41forkpty and some setup around that (raw termios + ECHO). And it is\r
42present in kernels at least after commit\r
43d945cb9cce20ac7143c2de8d88b187f62db99bdc (pty: Rework the pty layer to\r
44use the normal buffering logic) in 2.6.31-rc3.\r
45\r
46js: add more info to the commit log\r
47js: switch to bool\r
48js: lock unconditionally\r
49js: lock only the tty->ops->write call\r
50\r
51References: CVE-2014-0196\r
52Reported-and-tested-by: Jiri Slaby <jslaby@suse.cz>\r
53Signed-off-by: Peter Hurley <peter@hurleysoftware.com>\r
54Signed-off-by: Jiri Slaby <jslaby@suse.cz>\r
55Cc: Linus Torvalds <torvalds@linux-foundation.org>\r
56Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>\r
57Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>\r
58\r
59---\r
60 drivers/tty/n_tty.c | 4 ++++\r
61 1 file changed, 4 insertions(+)\r
62\r
63--- a/drivers/tty/n_tty.c\r
64+++ b/drivers/tty/n_tty.c\r
65@@ -2066,8 +2066,12 @@ static ssize_t n_tty_write(struct tty_st\r
66 if (tty->ops->flush_chars)\r
67 tty->ops->flush_chars(tty);\r
68 } else {\r
69+ struct n_tty_data *ldata = tty->disc_data;\r
70+\r
71 while (nr > 0) {\r
72+ mutex_lock(&ldata->output_lock);\r
73 c = tty->ops->write(tty, b, nr);\r
74+ mutex_unlock(&ldata->output_lock);\r
75 if (c < 0) {\r
76 retval = c;\r
77 goto break_out;\r
78\r