Skip to content

Commit 652788a

Browse files
committed
Merge tag 'tty-4.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial fixes from Greg KH: "Here are five fixes for the tty core and some serial drivers. The tty core ones fix some security and other issues reported by the syzbot that I have taken too long in responding to (sorry Tetsuo!). The 8350 serial driver fix resolves an issue of devices that used to work properly stopping working as they shouldn't have been added to a blacklist. All of these have been in linux-next for a few days with no reported issues" * tag 'tty-4.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: vt: prevent leaking uninitialized data to userspace via /dev/vcs* serdev: fix memleak on module unload serial: 8250_pci: Remove stalled entries in blacklist n_tty: Access echo_* variables carefully. n_tty: Fix stall at n_tty_receive_char_special().
2 parents c2aee37 + 21eff69 commit 652788a

File tree

4 files changed

+35
-27
lines changed

4 files changed

+35
-27
lines changed

drivers/tty/n_tty.c

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
127129
static 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

142144
static 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)
316319
static 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

811826
static 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

19071916
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)
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--;

drivers/tty/serdev/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ EXPORT_SYMBOL_GPL(__serdev_device_driver_register);
617617
static void __exit serdev_exit(void)
618618
{
619619
bus_unregister(&serdev_bus_type);
620+
ida_destroy(&ctrl_ida);
620621
}
621622
module_exit(serdev_exit);
622623

drivers/tty/serial/8250/8250_pci.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3339,9 +3339,7 @@ static const struct pci_device_id blacklist[] = {
33393339
/* multi-io cards handled by parport_serial */
33403340
{ PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */
33413341
{ PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */
3342-
{ PCI_DEVICE(0x4348, 0x7173), }, /* WCH CH355 4S */
33433342
{ PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */
3344-
{ PCI_DEVICE(0x1c00, 0x3470), }, /* WCH CH384 4S */
33453343

33463344
/* Moxa Smartio MUE boards handled by 8250_moxa */
33473345
{ PCI_VDEVICE(MOXA, 0x1024), },

drivers/tty/vt/vt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
784784
if (!*vc->vc_uni_pagedir_loc)
785785
con_set_default_unimap(vc);
786786

787-
vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
787+
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_KERNEL);
788788
if (!vc->vc_screenbuf)
789789
goto err_free;
790790

@@ -871,7 +871,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
871871

872872
if (new_screen_size > (4 << 20))
873873
return -EINVAL;
874-
newscreen = kmalloc(new_screen_size, GFP_USER);
874+
newscreen = kzalloc(new_screen_size, GFP_USER);
875875
if (!newscreen)
876876
return -ENOMEM;
877877

0 commit comments

Comments
 (0)