aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-14 15:29:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-14 15:29:59 -0500
commit779ee19da757d6bbf5504840f8b624f525de9797 (patch)
treec538becc24cb3a49b59d6ed782160a84dee8c1bb
parent9db8cc1ae5b0805230f710ddf4f2de0591db820a (diff)
parentc8053b58762745d93930826b60a4073854a15ce5 (diff)
Merge tag 'tty-4.5-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial fixes from Greg KH: "Here are a number of small tty and serial driver fixes for 4.5-rc4 that resolve some reported issues. One of them got reverted as it wasn't correct based on testing, and all have been in linux-next for a while" * tag 'tty-4.5-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: Revert "8250: uniphier: allow modular build with 8250 console" pty: make sure super_block is still valid in final /dev/tty close pty: fix possible use after free of tty->driver_data tty: Add support for PCIe WCH382 2S multi-IO card serial/omap: mark wait_for_xmitr as __maybe_unused serial: omap: Prevent DoS using unprivileged ioctl(TIOCSRS485) 8250: uniphier: allow modular build with 8250 console tty: Drop krefs for interrupted tty lock
-rw-r--r--drivers/tty/pty.c21
-rw-r--r--drivers/tty/serial/8250/8250_pci.c21
-rw-r--r--drivers/tty/serial/omap-serial.c10
-rw-r--r--drivers/tty/tty_io.c3
-rw-r--r--drivers/tty/tty_mutex.c7
-rw-r--r--fs/devpts/inode.c20
-rw-r--r--include/linux/devpts_fs.h4
7 files changed, 79 insertions, 7 deletions
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index b3110040164a..2348fa613707 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -681,7 +681,14 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
681/* this is called once with whichever end is closed last */ 681/* this is called once with whichever end is closed last */
682static void pty_unix98_shutdown(struct tty_struct *tty) 682static void pty_unix98_shutdown(struct tty_struct *tty)
683{ 683{
684 devpts_kill_index(tty->driver_data, tty->index); 684 struct inode *ptmx_inode;
685
686 if (tty->driver->subtype == PTY_TYPE_MASTER)
687 ptmx_inode = tty->driver_data;
688 else
689 ptmx_inode = tty->link->driver_data;
690 devpts_kill_index(ptmx_inode, tty->index);
691 devpts_del_ref(ptmx_inode);
685} 692}
686 693
687static const struct tty_operations ptm_unix98_ops = { 694static const struct tty_operations ptm_unix98_ops = {
@@ -773,6 +780,18 @@ static int ptmx_open(struct inode *inode, struct file *filp)
773 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ 780 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
774 tty->driver_data = inode; 781 tty->driver_data = inode;
775 782
783 /*
784 * In the case where all references to ptmx inode are dropped and we
785 * still have /dev/tty opened pointing to the master/slave pair (ptmx
786 * is closed/released before /dev/tty), we must make sure that the inode
787 * is still valid when we call the final pty_unix98_shutdown, thus we
788 * hold an additional reference to the ptmx inode. For the same /dev/tty
789 * last close case, we also need to make sure the super_block isn't
790 * destroyed (devpts instance unmounted), before /dev/tty is closed and
791 * on its release devpts_kill_index is called.
792 */
793 devpts_add_ref(inode);
794
776 tty_add_file(tty, filp); 795 tty_add_file(tty, filp);
777 796
778 slave_inode = devpts_pty_new(inode, 797 slave_inode = devpts_pty_new(inode,
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index e71ec78fc11e..7cd6f9a90542 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1941,6 +1941,7 @@ pci_wch_ch38x_setup(struct serial_private *priv,
1941#define PCIE_VENDOR_ID_WCH 0x1c00 1941#define PCIE_VENDOR_ID_WCH 0x1c00
1942#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250 1942#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
1943#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470 1943#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
1944#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253
1944 1945
1945#define PCI_VENDOR_ID_PERICOM 0x12D8 1946#define PCI_VENDOR_ID_PERICOM 0x12D8
1946#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951 1947#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
@@ -2637,6 +2638,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
2637 .subdevice = PCI_ANY_ID, 2638 .subdevice = PCI_ANY_ID,
2638 .setup = pci_wch_ch353_setup, 2639 .setup = pci_wch_ch353_setup,
2639 }, 2640 },
2641 /* WCH CH382 2S card (16850 clone) */
2642 {
2643 .vendor = PCIE_VENDOR_ID_WCH,
2644 .device = PCIE_DEVICE_ID_WCH_CH382_2S,
2645 .subvendor = PCI_ANY_ID,
2646 .subdevice = PCI_ANY_ID,
2647 .setup = pci_wch_ch38x_setup,
2648 },
2640 /* WCH CH382 2S1P card (16850 clone) */ 2649 /* WCH CH382 2S1P card (16850 clone) */
2641 { 2650 {
2642 .vendor = PCIE_VENDOR_ID_WCH, 2651 .vendor = PCIE_VENDOR_ID_WCH,
@@ -2955,6 +2964,7 @@ enum pci_board_num_t {
2955 pbn_fintek_4, 2964 pbn_fintek_4,
2956 pbn_fintek_8, 2965 pbn_fintek_8,
2957 pbn_fintek_12, 2966 pbn_fintek_12,
2967 pbn_wch382_2,
2958 pbn_wch384_4, 2968 pbn_wch384_4,
2959 pbn_pericom_PI7C9X7951, 2969 pbn_pericom_PI7C9X7951,
2960 pbn_pericom_PI7C9X7952, 2970 pbn_pericom_PI7C9X7952,
@@ -3775,6 +3785,13 @@ static struct pciserial_board pci_boards[] = {
3775 .base_baud = 115200, 3785 .base_baud = 115200,
3776 .first_offset = 0x40, 3786 .first_offset = 0x40,
3777 }, 3787 },
3788 [pbn_wch382_2] = {
3789 .flags = FL_BASE0,
3790 .num_ports = 2,
3791 .base_baud = 115200,
3792 .uart_offset = 8,
3793 .first_offset = 0xC0,
3794 },
3778 [pbn_wch384_4] = { 3795 [pbn_wch384_4] = {
3779 .flags = FL_BASE0, 3796 .flags = FL_BASE0,
3780 .num_ports = 4, 3797 .num_ports = 4,
@@ -5574,6 +5591,10 @@ static struct pci_device_id serial_pci_tbl[] = {
5574 PCI_ANY_ID, PCI_ANY_ID, 5591 PCI_ANY_ID, PCI_ANY_ID,
5575 0, 0, pbn_b0_bt_2_115200 }, 5592 0, 0, pbn_b0_bt_2_115200 },
5576 5593
5594 { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S,
5595 PCI_ANY_ID, PCI_ANY_ID,
5596 0, 0, pbn_wch382_2 },
5597
5577 { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S, 5598 { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S,
5578 PCI_ANY_ID, PCI_ANY_ID, 5599 PCI_ANY_ID, PCI_ANY_ID,
5579 0, 0, pbn_wch384_4 }, 5600 0, 0, pbn_wch384_4 },
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index b645f9228ed7..fa49eb1e2fa2 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1165,7 +1165,7 @@ serial_omap_type(struct uart_port *port)
1165 1165
1166#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) 1166#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
1167 1167
1168static void wait_for_xmitr(struct uart_omap_port *up) 1168static void __maybe_unused wait_for_xmitr(struct uart_omap_port *up)
1169{ 1169{
1170 unsigned int status, tmout = 10000; 1170 unsigned int status, tmout = 10000;
1171 1171
@@ -1343,7 +1343,7 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up)
1343 1343
1344/* Enable or disable the rs485 support */ 1344/* Enable or disable the rs485 support */
1345static int 1345static int
1346serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) 1346serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
1347{ 1347{
1348 struct uart_omap_port *up = to_uart_omap_port(port); 1348 struct uart_omap_port *up = to_uart_omap_port(port);
1349 unsigned int mode; 1349 unsigned int mode;
@@ -1356,8 +1356,12 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
1356 up->ier = 0; 1356 up->ier = 0;
1357 serial_out(up, UART_IER, 0); 1357 serial_out(up, UART_IER, 0);
1358 1358
1359 /* Clamp the delays to [0, 100ms] */
1360 rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
1361 rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
1362
1359 /* store new config */ 1363 /* store new config */
1360 port->rs485 = *rs485conf; 1364 port->rs485 = *rs485;
1361 1365
1362 /* 1366 /*
1363 * Just as a precaution, only allow rs485 1367 * Just as a precaution, only allow rs485
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 5cec01c75691..a7eacef1bd22 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2066,13 +2066,12 @@ retry_open:
2066 if (tty) { 2066 if (tty) {
2067 mutex_unlock(&tty_mutex); 2067 mutex_unlock(&tty_mutex);
2068 retval = tty_lock_interruptible(tty); 2068 retval = tty_lock_interruptible(tty);
2069 tty_kref_put(tty); /* drop kref from tty_driver_lookup_tty() */
2069 if (retval) { 2070 if (retval) {
2070 if (retval == -EINTR) 2071 if (retval == -EINTR)
2071 retval = -ERESTARTSYS; 2072 retval = -ERESTARTSYS;
2072 goto err_unref; 2073 goto err_unref;
2073 } 2074 }
2074 /* safe to drop the kref from tty_driver_lookup_tty() */
2075 tty_kref_put(tty);
2076 retval = tty_reopen(tty); 2075 retval = tty_reopen(tty);
2077 if (retval < 0) { 2076 if (retval < 0) {
2078 tty_unlock(tty); 2077 tty_unlock(tty);
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index d2f3c4cd697f..dfa9ec03fa8e 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -21,10 +21,15 @@ EXPORT_SYMBOL(tty_lock);
21 21
22int tty_lock_interruptible(struct tty_struct *tty) 22int tty_lock_interruptible(struct tty_struct *tty)
23{ 23{
24 int ret;
25
24 if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) 26 if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
25 return -EIO; 27 return -EIO;
26 tty_kref_get(tty); 28 tty_kref_get(tty);
27 return mutex_lock_interruptible(&tty->legacy_mutex); 29 ret = mutex_lock_interruptible(&tty->legacy_mutex);
30 if (ret)
31 tty_kref_put(tty);
32 return ret;
28} 33}
29 34
30void __lockfunc tty_unlock(struct tty_struct *tty) 35void __lockfunc tty_unlock(struct tty_struct *tty)
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 1f107fd51328..655f21f99160 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -575,6 +575,26 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
575 mutex_unlock(&allocated_ptys_lock); 575 mutex_unlock(&allocated_ptys_lock);
576} 576}
577 577
578/*
579 * pty code needs to hold extra references in case of last /dev/tty close
580 */
581
582void devpts_add_ref(struct inode *ptmx_inode)
583{
584 struct super_block *sb = pts_sb_from_inode(ptmx_inode);
585
586 atomic_inc(&sb->s_active);
587 ihold(ptmx_inode);
588}
589
590void devpts_del_ref(struct inode *ptmx_inode)
591{
592 struct super_block *sb = pts_sb_from_inode(ptmx_inode);
593
594 iput(ptmx_inode);
595 deactivate_super(sb);
596}
597
578/** 598/**
579 * devpts_pty_new -- create a new inode in /dev/pts/ 599 * devpts_pty_new -- create a new inode in /dev/pts/
580 * @ptmx_inode: inode of the master 600 * @ptmx_inode: inode of the master
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
index 251a2090a554..e0ee0b3000b2 100644
--- a/include/linux/devpts_fs.h
+++ b/include/linux/devpts_fs.h
@@ -19,6 +19,8 @@
19 19
20int devpts_new_index(struct inode *ptmx_inode); 20int devpts_new_index(struct inode *ptmx_inode);
21void devpts_kill_index(struct inode *ptmx_inode, int idx); 21void devpts_kill_index(struct inode *ptmx_inode, int idx);
22void devpts_add_ref(struct inode *ptmx_inode);
23void devpts_del_ref(struct inode *ptmx_inode);
22/* mknod in devpts */ 24/* mknod in devpts */
23struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index, 25struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
24 void *priv); 26 void *priv);
@@ -32,6 +34,8 @@ void devpts_pty_kill(struct inode *inode);
32/* Dummy stubs in the no-pty case */ 34/* Dummy stubs in the no-pty case */
33static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; } 35static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
34static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { } 36static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
37static inline void devpts_add_ref(struct inode *ptmx_inode) { }
38static inline void devpts_del_ref(struct inode *ptmx_inode) { }
35static inline struct inode *devpts_pty_new(struct inode *ptmx_inode, 39static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
36 dev_t device, int index, void *priv) 40 dev_t device, int index, void *priv)
37{ 41{