aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2018-05-25 20:53:13 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-06-28 08:30:16 -0400
commit3d63b7e4ae0dc5e02d28ddd2fa1f945defc68d81 (patch)
tree4c72cbec570647876d8060aa4cb85cc4f3dfb796
parent7daf201d7fe8334e2d2364d4e8ed3394ec9af819 (diff)
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 Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Reported-by: syzbot <syzbot+18df353d7540aa6b5467@syzkaller.appspotmail.com> Fixes: bc5a5e3f45d04784 ("n_tty: Don't wrap input buffer indices at buffer size") Cc: stable <stable@vger.kernel.org> Cc: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/n_tty.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index cbe98bc2b998..b279f8730e04 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -124,6 +124,8 @@ struct n_tty_data {
124 struct mutex output_lock; 124 struct mutex output_lock;
125}; 125};
126 126
127#define MASK(x) ((x) & (N_TTY_BUF_SIZE - 1))
128
127static inline size_t read_cnt(struct n_tty_data *ldata) 129static inline size_t read_cnt(struct n_tty_data *ldata)
128{ 130{
129 return ldata->read_head - ldata->read_tail; 131 return ldata->read_head - ldata->read_tail;
@@ -978,14 +980,15 @@ static void eraser(unsigned char c, struct tty_struct *tty)
978 } 980 }
979 981
980 seen_alnums = 0; 982 seen_alnums = 0;
981 while (ldata->read_head != ldata->canon_head) { 983 while (MASK(ldata->read_head) != MASK(ldata->canon_head)) {
982 head = ldata->read_head; 984 head = ldata->read_head;
983 985
984 /* erase a single possibly multibyte character */ 986 /* erase a single possibly multibyte character */
985 do { 987 do {
986 head--; 988 head--;
987 c = read_buf(ldata, head); 989 c = read_buf(ldata, head);
988 } while (is_continuation(c, tty) && head != ldata->canon_head); 990 } while (is_continuation(c, tty) &&
991 MASK(head) != MASK(ldata->canon_head));
989 992
990 /* do not partially erase */ 993 /* do not partially erase */
991 if (is_continuation(c, tty)) 994 if (is_continuation(c, tty))
@@ -1027,7 +1030,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
1027 * This info is used to go back the correct 1030 * This info is used to go back the correct
1028 * number of columns. 1031 * number of columns.
1029 */ 1032 */
1030 while (tail != ldata->canon_head) { 1033 while (MASK(tail) != MASK(ldata->canon_head)) {
1031 tail--; 1034 tail--;
1032 c = read_buf(ldata, tail); 1035 c = read_buf(ldata, tail);
1033 if (c == '\t') { 1036 if (c == '\t') {
@@ -1302,7 +1305,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
1302 finish_erasing(ldata); 1305 finish_erasing(ldata);
1303 echo_char(c, tty); 1306 echo_char(c, tty);
1304 echo_char_raw('\n', ldata); 1307 echo_char_raw('\n', ldata);
1305 while (tail != ldata->read_head) { 1308 while (MASK(tail) != MASK(ldata->read_head)) {
1306 echo_char(read_buf(ldata, tail), tty); 1309 echo_char(read_buf(ldata, tail), tty);
1307 tail++; 1310 tail++;
1308 } 1311 }
@@ -2411,7 +2414,7 @@ static unsigned long inq_canon(struct n_tty_data *ldata)
2411 tail = ldata->read_tail; 2414 tail = ldata->read_tail;
2412 nr = head - tail; 2415 nr = head - tail;
2413 /* Skip EOF-chars.. */ 2416 /* Skip EOF-chars.. */
2414 while (head != tail) { 2417 while (MASK(head) != MASK(tail)) {
2415 if (test_bit(tail & (N_TTY_BUF_SIZE - 1), ldata->read_flags) && 2418 if (test_bit(tail & (N_TTY_BUF_SIZE - 1), ldata->read_flags) &&
2416 read_buf(ldata, tail) == __DISABLED_CHAR) 2419 read_buf(ldata, tail) == __DISABLED_CHAR)
2417 nr--; 2420 nr--;