@@ -124,6 +124,8 @@ struct n_tty_data {
124124 struct mutex output_lock ;
125125};
126126
127+ #define MASK (x ) ((x) & (N_TTY_BUF_SIZE - 1))
128+
127129static inline size_t read_cnt (struct n_tty_data * ldata )
128130{
129131 return ldata -> read_head - ldata -> read_tail ;
@@ -141,6 +143,7 @@ static inline unsigned char *read_buf_addr(struct n_tty_data *ldata, size_t i)
141143
142144static inline unsigned char echo_buf (struct n_tty_data * ldata , size_t i )
143145{
146+ smp_rmb (); /* Matches smp_wmb() in add_echo_byte(). */
144147 return ldata -> echo_buf [i & (N_TTY_BUF_SIZE - 1 )];
145148}
146149
@@ -316,9 +319,7 @@ static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
316319static void reset_buffer_flags (struct n_tty_data * ldata )
317320{
318321 ldata -> read_head = ldata -> canon_head = ldata -> read_tail = 0 ;
319- ldata -> echo_head = ldata -> echo_tail = ldata -> echo_commit = 0 ;
320322 ldata -> commit_head = 0 ;
321- ldata -> echo_mark = 0 ;
322323 ldata -> line_start = 0 ;
323324
324325 ldata -> erasing = 0 ;
@@ -617,12 +618,19 @@ static size_t __process_echoes(struct tty_struct *tty)
617618 old_space = space = tty_write_room (tty );
618619
619620 tail = ldata -> echo_tail ;
620- while (ldata -> echo_commit != tail ) {
621+ while (MASK ( ldata -> echo_commit ) != MASK ( tail ) ) {
621622 c = echo_buf (ldata , tail );
622623 if (c == ECHO_OP_START ) {
623624 unsigned char op ;
624625 int no_space_left = 0 ;
625626
627+ /*
628+ * Since add_echo_byte() is called without holding
629+ * output_lock, we might see only portion of multi-byte
630+ * operation.
631+ */
632+ if (MASK (ldata -> echo_commit ) == MASK (tail + 1 ))
633+ goto not_yet_stored ;
626634 /*
627635 * If the buffer byte is the start of a multi-byte
628636 * operation, get the next byte, which is either the
@@ -634,6 +642,8 @@ static size_t __process_echoes(struct tty_struct *tty)
634642 unsigned int num_chars , num_bs ;
635643
636644 case ECHO_OP_ERASE_TAB :
645+ if (MASK (ldata -> echo_commit ) == MASK (tail + 2 ))
646+ goto not_yet_stored ;
637647 num_chars = echo_buf (ldata , tail + 2 );
638648
639649 /*
@@ -728,7 +738,8 @@ static size_t __process_echoes(struct tty_struct *tty)
728738 /* If the echo buffer is nearly full (so that the possibility exists
729739 * of echo overrun before the next commit), then discard enough
730740 * data at the tail to prevent a subsequent overrun */
731- while (ldata -> echo_commit - tail >= ECHO_DISCARD_WATERMARK ) {
741+ while (ldata -> echo_commit > tail &&
742+ ldata -> echo_commit - tail >= ECHO_DISCARD_WATERMARK ) {
732743 if (echo_buf (ldata , tail ) == ECHO_OP_START ) {
733744 if (echo_buf (ldata , tail + 1 ) == ECHO_OP_ERASE_TAB )
734745 tail += 3 ;
@@ -738,6 +749,7 @@ static size_t __process_echoes(struct tty_struct *tty)
738749 tail ++ ;
739750 }
740751
752+ not_yet_stored :
741753 ldata -> echo_tail = tail ;
742754 return old_space - space ;
743755}
@@ -748,6 +760,7 @@ static void commit_echoes(struct tty_struct *tty)
748760 size_t nr , old , echoed ;
749761 size_t head ;
750762
763+ mutex_lock (& ldata -> output_lock );
751764 head = ldata -> echo_head ;
752765 ldata -> echo_mark = head ;
753766 old = ldata -> echo_commit - ldata -> echo_tail ;
@@ -756,10 +769,12 @@ static void commit_echoes(struct tty_struct *tty)
756769 * is over the threshold (and try again each time another
757770 * block is accumulated) */
758771 nr = head - ldata -> echo_tail ;
759- if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK ))
772+ if (nr < ECHO_COMMIT_WATERMARK ||
773+ (nr % ECHO_BLOCK > old % ECHO_BLOCK )) {
774+ mutex_unlock (& ldata -> output_lock );
760775 return ;
776+ }
761777
762- mutex_lock (& ldata -> output_lock );
763778 ldata -> echo_commit = head ;
764779 echoed = __process_echoes (tty );
765780 mutex_unlock (& ldata -> output_lock );
@@ -810,7 +825,9 @@ static void flush_echoes(struct tty_struct *tty)
810825
811826static inline void add_echo_byte (unsigned char c , struct n_tty_data * ldata )
812827{
813- * echo_buf_addr (ldata , ldata -> echo_head ++ ) = c ;
828+ * echo_buf_addr (ldata , ldata -> echo_head ) = c ;
829+ smp_wmb (); /* Matches smp_rmb() in echo_buf(). */
830+ ldata -> echo_head ++ ;
814831}
815832
816833/**
@@ -978,14 +995,15 @@ static void eraser(unsigned char c, struct tty_struct *tty)
978995 }
979996
980997 seen_alnums = 0 ;
981- while (ldata -> read_head != ldata -> canon_head ) {
998+ while (MASK ( ldata -> read_head ) != MASK ( ldata -> canon_head ) ) {
982999 head = ldata -> read_head ;
9831000
9841001 /* erase a single possibly multibyte character */
9851002 do {
9861003 head -- ;
9871004 c = read_buf (ldata , head );
988- } while (is_continuation (c , tty ) && head != ldata -> canon_head );
1005+ } while (is_continuation (c , tty ) &&
1006+ MASK (head ) != MASK (ldata -> canon_head ));
9891007
9901008 /* do not partially erase */
9911009 if (is_continuation (c , tty ))
@@ -1027,7 +1045,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
10271045 * This info is used to go back the correct
10281046 * number of columns.
10291047 */
1030- while (tail != ldata -> canon_head ) {
1048+ while (MASK ( tail ) != MASK ( ldata -> canon_head ) ) {
10311049 tail -- ;
10321050 c = read_buf (ldata , tail );
10331051 if (c == '\t' ) {
@@ -1302,7 +1320,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
13021320 finish_erasing (ldata );
13031321 echo_char (c , tty );
13041322 echo_char_raw ('\n' , ldata );
1305- while (tail != ldata -> read_head ) {
1323+ while (MASK ( tail ) != MASK ( ldata -> read_head ) ) {
13061324 echo_char (read_buf (ldata , tail ), tty );
13071325 tail ++ ;
13081326 }
@@ -1878,30 +1896,21 @@ static int n_tty_open(struct tty_struct *tty)
18781896 struct n_tty_data * ldata ;
18791897
18801898 /* Currently a malloc failure here can panic */
1881- ldata = vmalloc (sizeof (* ldata ));
1899+ ldata = vzalloc (sizeof (* ldata ));
18821900 if (!ldata )
1883- goto err ;
1901+ return - ENOMEM ;
18841902
18851903 ldata -> overrun_time = jiffies ;
18861904 mutex_init (& ldata -> atomic_read_lock );
18871905 mutex_init (& ldata -> output_lock );
18881906
18891907 tty -> disc_data = ldata ;
1890- reset_buffer_flags (tty -> disc_data );
1891- ldata -> column = 0 ;
1892- ldata -> canon_column = 0 ;
1893- ldata -> num_overrun = 0 ;
1894- ldata -> no_room = 0 ;
1895- ldata -> lnext = 0 ;
18961908 tty -> closing = 0 ;
18971909 /* indicate buffer work may resume */
18981910 clear_bit (TTY_LDISC_HALTED , & tty -> flags );
18991911 n_tty_set_termios (tty , NULL );
19001912 tty_unthrottle (tty );
1901-
19021913 return 0 ;
1903- err :
1904- return - ENOMEM ;
19051914}
19061915
19071916static inline int input_available_p (struct tty_struct * tty , int poll )
@@ -2411,7 +2420,7 @@ static unsigned long inq_canon(struct n_tty_data *ldata)
24112420 tail = ldata -> read_tail ;
24122421 nr = head - tail ;
24132422 /* Skip EOF-chars.. */
2414- while (head != tail ) {
2423+ while (MASK ( head ) != MASK ( tail ) ) {
24152424 if (test_bit (tail & (N_TTY_BUF_SIZE - 1 ), ldata -> read_flags ) &&
24162425 read_buf (ldata , tail ) == __DISABLED_CHAR )
24172426 nr -- ;
0 commit comments