]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.36.2/tty-don-t-allow-reopen-when-ldisc-is-changing.patch
Fixes for 5.10
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / tty-don-t-allow-reopen-when-ldisc-is-changing.patch
CommitLineData
53c49429
GKH
1From e2efafbf139d2bfdfe96f2901f03189fecd172e4 Mon Sep 17 00:00:00 2001
2From: Jiri Slaby <jslaby@suse.cz>
3Date: Mon, 29 Nov 2010 10:16:53 +0100
4Subject: TTY: don't allow reopen when ldisc is changing
5
6From: Jiri Slaby <jslaby@suse.cz>
7
8commit e2efafbf139d2bfdfe96f2901f03189fecd172e4 upstream.
9
10There are many WARNINGs like the following reported nowadays:
11WARNING: at drivers/tty/tty_io.c:1331 tty_open+0x2a2/0x49a()
12Hardware name: Latitude E6500
13Modules linked in:
14Pid: 1207, comm: plymouthd Not tainted 2.6.37-rc3-mmotm1123 #3
15Call Trace:
16 [<ffffffff8103b189>] warn_slowpath_common+0x80/0x98
17 [<ffffffff8103b1b6>] warn_slowpath_null+0x15/0x17
18 [<ffffffff8128a3ab>] tty_open+0x2a2/0x49a
19 [<ffffffff810fd53f>] chrdev_open+0x11d/0x146
20...
21
22This means tty_reopen is called without TTY_LDISC set. For further
23considerations, note tty_lock is held in tty_open. TTY_LDISC is cleared in:
241) __tty_hangup from tty_ldisc_hangup to tty_ldisc_enable. During this
25section tty_lock is held. However tty_lock is temporarily dropped in
26the middle of the function by tty_ldisc_hangup.
27
282) tty_release via tty_ldisc_release till the end of tty existence. If
29tty->count <= 1, tty_lock is taken, TTY_CLOSING bit set and then
30tty_ldisc_release called. tty_reopen checks TTY_CLOSING before checking
31TTY_LDISC.
32
333) tty_set_ldisc from tty_ldisc_halt to tty_ldisc_enable. We:
34 * take tty_lock, set TTY_LDISC_CHANGING, put tty_lock
35 * call tty_ldisc_halt (clear TTY_LDISC), tty_lock is _not_ held
36 * do some other work
37 * take tty_lock, call tty_ldisc_enable (set TTY_LDISC), put
38 tty_lock
39
40I cannot see how 2) can be a problem, as there I see no race. OTOH, 1)
41and 3) can happen without problems. This patch the case 3) by checking
42TTY_LDISC_CHANGING along with TTY_CLOSING in tty_reopen. 1) will be
43fixed in the following patch.
44
45Nicely reproducible with two processes:
46while (1) {
47 fd = open("/dev/ttyS1", O_RDWR);
48 if (fd < 0) {
49 warn("open");
50 continue;
51 }
52 close(fd);
53}
54--------
55while (1) {
56 fd = open("/dev/ttyS1", O_RDWR);
57 ld1 = 0; ld2 = 2;
58 while (1) {
59 ioctl(fd, TIOCSETD, &ld1);
60 ioctl(fd, TIOCSETD, &ld2);
61 }
62 close(fd);
63}
64
65Signed-off-by: Jiri Slaby <jslaby@suse.cz>
66Reported-by: <Valdis.Kletnieks@vt.edu>
67Cc: Kyle McMartin <kyle@mcmartin.ca>
68Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
69Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
70
71---
72 drivers/char/tty_io.c | 3 ++-
73 1 file changed, 2 insertions(+), 1 deletion(-)
74
75--- a/drivers/char/tty_io.c
76+++ b/drivers/char/tty_io.c
77@@ -1304,7 +1304,8 @@ static int tty_reopen(struct tty_struct
78 {
79 struct tty_driver *driver = tty->driver;
80
81- if (test_bit(TTY_CLOSING, &tty->flags))
82+ if (test_bit(TTY_CLOSING, &tty->flags) ||
83+ test_bit(TTY_LDISC_CHANGING, &tty->flags))
84 return -EIO;
85
86 if (driver->type == TTY_DRIVER_TYPE_PTY &&