@@ -124,6 +124,8 @@ struct n_tty_data {
124
124
struct mutex output_lock ;
125
125
};
126
126
127
+ #define MASK (x ) ((x) & (N_TTY_BUF_SIZE - 1))
128
+
127
129
static inline size_t read_cnt (struct n_tty_data * ldata )
128
130
{
129
131
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)
141
143
142
144
static inline unsigned char echo_buf (struct n_tty_data * ldata , size_t i )
143
145
{
146
+ smp_rmb (); /* Matches smp_wmb() in add_echo_byte(). */
144
147
return ldata -> echo_buf [i & (N_TTY_BUF_SIZE - 1 )];
145
148
}
146
149
@@ -316,9 +319,7 @@ static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
316
319
static void reset_buffer_flags (struct n_tty_data * ldata )
317
320
{
318
321
ldata -> read_head = ldata -> canon_head = ldata -> read_tail = 0 ;
319
- ldata -> echo_head = ldata -> echo_tail = ldata -> echo_commit = 0 ;
320
322
ldata -> commit_head = 0 ;
321
- ldata -> echo_mark = 0 ;
322
323
ldata -> line_start = 0 ;
323
324
324
325
ldata -> erasing = 0 ;
@@ -617,12 +618,19 @@ static size_t __process_echoes(struct tty_struct *tty)
617
618
old_space = space = tty_write_room (tty );
618
619
619
620
tail = ldata -> echo_tail ;
620
- while (ldata -> echo_commit != tail ) {
621
+ while (MASK ( ldata -> echo_commit ) != MASK ( tail ) ) {
621
622
c = echo_buf (ldata , tail );
622
623
if (c == ECHO_OP_START ) {
623
624
unsigned char op ;
624
625
int no_space_left = 0 ;
625
626
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 ;
626
634
/*
627
635
* If the buffer byte is the start of a multi-byte
628
636
* operation, get the next byte, which is either the
@@ -634,6 +642,8 @@ static size_t __process_echoes(struct tty_struct *tty)
634
642
unsigned int num_chars , num_bs ;
635
643
636
644
case ECHO_OP_ERASE_TAB :
645
+ if (MASK (ldata -> echo_commit ) == MASK (tail + 2 ))
646
+ goto not_yet_stored ;
637
647
num_chars = echo_buf (ldata , tail + 2 );
638
648
639
649
/*
@@ -728,7 +738,8 @@ static size_t __process_echoes(struct tty_struct *tty)
728
738
/* If the echo buffer is nearly full (so that the possibility exists
729
739
* of echo overrun before the next commit), then discard enough
730
740
* 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 ) {
732
743
if (echo_buf (ldata , tail ) == ECHO_OP_START ) {
733
744
if (echo_buf (ldata , tail + 1 ) == ECHO_OP_ERASE_TAB )
734
745
tail += 3 ;
@@ -738,6 +749,7 @@ static size_t __process_echoes(struct tty_struct *tty)
738
749
tail ++ ;
739
750
}
740
751
752
+ not_yet_stored :
741
753
ldata -> echo_tail = tail ;
742
754
return old_space - space ;
743
755
}
@@ -748,6 +760,7 @@ static void commit_echoes(struct tty_struct *tty)
748
760
size_t nr , old , echoed ;
749
761
size_t head ;
750
762
763
+ mutex_lock (& ldata -> output_lock );
751
764
head = ldata -> echo_head ;
752
765
ldata -> echo_mark = head ;
753
766
old = ldata -> echo_commit - ldata -> echo_tail ;
@@ -756,10 +769,12 @@ static void commit_echoes(struct tty_struct *tty)
756
769
* is over the threshold (and try again each time another
757
770
* block is accumulated) */
758
771
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 );
760
775
return ;
776
+ }
761
777
762
- mutex_lock (& ldata -> output_lock );
763
778
ldata -> echo_commit = head ;
764
779
echoed = __process_echoes (tty );
765
780
mutex_unlock (& ldata -> output_lock );
@@ -810,7 +825,9 @@ static void flush_echoes(struct tty_struct *tty)
810
825
811
826
static inline void add_echo_byte (unsigned char c , struct n_tty_data * ldata )
812
827
{
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 ++ ;
814
831
}
815
832
816
833
/**
@@ -978,14 +995,15 @@ static void eraser(unsigned char c, struct tty_struct *tty)
978
995
}
979
996
980
997
seen_alnums = 0 ;
981
- while (ldata -> read_head != ldata -> canon_head ) {
998
+ while (MASK ( ldata -> read_head ) != MASK ( ldata -> canon_head ) ) {
982
999
head = ldata -> read_head ;
983
1000
984
1001
/* erase a single possibly multibyte character */
985
1002
do {
986
1003
head -- ;
987
1004
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 ));
989
1007
990
1008
/* do not partially erase */
991
1009
if (is_continuation (c , tty ))
@@ -1027,7 +1045,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
1027
1045
* This info is used to go back the correct
1028
1046
* number of columns.
1029
1047
*/
1030
- while (tail != ldata -> canon_head ) {
1048
+ while (MASK ( tail ) != MASK ( ldata -> canon_head ) ) {
1031
1049
tail -- ;
1032
1050
c = read_buf (ldata , tail );
1033
1051
if (c == '\t' ) {
@@ -1302,7 +1320,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
1302
1320
finish_erasing (ldata );
1303
1321
echo_char (c , tty );
1304
1322
echo_char_raw ('\n' , ldata );
1305
- while (tail != ldata -> read_head ) {
1323
+ while (MASK ( tail ) != MASK ( ldata -> read_head ) ) {
1306
1324
echo_char (read_buf (ldata , tail ), tty );
1307
1325
tail ++ ;
1308
1326
}
@@ -1878,30 +1896,21 @@ static int n_tty_open(struct tty_struct *tty)
1878
1896
struct n_tty_data * ldata ;
1879
1897
1880
1898
/* Currently a malloc failure here can panic */
1881
- ldata = vmalloc (sizeof (* ldata ));
1899
+ ldata = vzalloc (sizeof (* ldata ));
1882
1900
if (!ldata )
1883
- goto err ;
1901
+ return - ENOMEM ;
1884
1902
1885
1903
ldata -> overrun_time = jiffies ;
1886
1904
mutex_init (& ldata -> atomic_read_lock );
1887
1905
mutex_init (& ldata -> output_lock );
1888
1906
1889
1907
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 ;
1896
1908
tty -> closing = 0 ;
1897
1909
/* indicate buffer work may resume */
1898
1910
clear_bit (TTY_LDISC_HALTED , & tty -> flags );
1899
1911
n_tty_set_termios (tty , NULL );
1900
1912
tty_unthrottle (tty );
1901
-
1902
1913
return 0 ;
1903
- err :
1904
- return - ENOMEM ;
1905
1914
}
1906
1915
1907
1916
static 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)
2411
2420
tail = ldata -> read_tail ;
2412
2421
nr = head - tail ;
2413
2422
/* Skip EOF-chars.. */
2414
- while (head != tail ) {
2423
+ while (MASK ( head ) != MASK ( tail ) ) {
2415
2424
if (test_bit (tail & (N_TTY_BUF_SIZE - 1 ), ldata -> read_flags ) &&
2416
2425
read_buf (ldata , tail ) == __DISABLED_CHAR )
2417
2426
nr -- ;
0 commit comments