patch "n_tty: Fix stall at n_tty_receive_char_special()." added to tty-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
n_tty: Fix stall at n_tty_receive_char_special().
to my tty git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
in the tty-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
Quoted 1 line
From
3d63b7e4ae0dc5e02d28ddd2fa1f945defc68d81Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <[email protected]>
Date: Sat, 26 May 2018 09:53:13 +0900
Subject: n_tty: Fix stall at n_tty_receive_char_special().
syzbot is reporting stalls at n_tty_receive_char_special() [1]. This is because comparison is not working as expected since ldata->read_head can change at any moment. Mitigate this by explicitly masking with buffer size when checking condition for "while" loops.
[1] https://syzkaller.appspot.com/bug?id=3d7481a346958d9469bebbeb0537d5f056bdd6e8
--- drivers/tty/n_tty.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/tty/n_tty.c +8 -5
@@ -124,6 +124,8 @@ struct n_tty_data {struct mutex output_lock; }; +#define MASK (x) ((x) & (N_TTY_BUF_SIZE - 1)) +static inline size_t read_cnt (struct n_tty_data *ldata) {return ldata->read_head - ldata->read_tail;
@@ -978,14 +980,15 @@ static void eraser(unsigned char c, struct tty_struct *tty) } seen_alnums =0 ; -while (ldata->read_head != ldata->canon_head) { +while (MASK (ldata->read_head) !=MASK (ldata->canon_head)) { head = ldata->read_head;/* erase a single possibly multibyte character */ do { head--; c =read_buf (ldata, head); - }while (is_continuation (c, tty) && head != ldata->canon_head); + }while (is_continuation (c, tty) && +MASK (head) !=MASK (ldata->canon_head));/* do not partially erase */ if (is_continuation (c, tty))
@@ -1027,7 +1030,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)* This info is used to go back the correct * number of columns. */ -while (tail != ldata->canon_head) { +while (MASK (tail) !=MASK (ldata->canon_head)) { tail--; c =read_buf (ldata, tail);if (c =='\t' ) {
@@ -1302,7 +1305,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)finish_erasing (ldata);echo_char (c, tty);echo_char_raw ('\n' , ldata); -while (tail != ldata->read_head) { +while (MASK (tail) !=MASK (ldata->read_head)) {echo_char (read_buf (ldata, tail), tty); tail++; }
@@ -2411,7 +2414,7 @@ static unsigned long inq_canon(struct n_tty_data *ldata) tail = ldata->read_tail; nr = head - tail;/* Skip EOF-chars.. */ -while (head != tail) { +while (MASK (head) !=MASK (tail)) {if (test_bit (tail & (N_TTY_BUF_SIZE -1 ), ldata->read_flags) &&read_buf (ldata, tail) == __DISABLED_CHAR) nr--;
Signature · 1 line
2.18.0