Skip to content

Commit 779ee19

Browse files
committed
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
2 parents 9db8cc1 + c8053b5 commit 779ee19

File tree

7 files changed

+79
-7
lines changed

7 files changed

+79
-7
lines changed

drivers/tty/pty.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,14 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
681681
/* this is called once with whichever end is closed last */
682682
static void pty_unix98_shutdown(struct tty_struct *tty)
683683
{
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);
685692
}
686693

687694
static const struct tty_operations ptm_unix98_ops = {
@@ -773,6 +780,18 @@ static int ptmx_open(struct inode *inode, struct file *filp)
773780
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
774781
tty->driver_data = inode;
775782

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+
776795
tty_add_file(tty, filp);
777796

778797
slave_inode = devpts_pty_new(inode,

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,6 +1941,7 @@ pci_wch_ch38x_setup(struct serial_private *priv,
19411941
#define PCIE_VENDOR_ID_WCH 0x1c00
19421942
#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
19431943
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
1944+
#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253
19441945

19451946
#define PCI_VENDOR_ID_PERICOM 0x12D8
19461947
#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
@@ -2637,6 +2638,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
26372638
.subdevice = PCI_ANY_ID,
26382639
.setup = pci_wch_ch353_setup,
26392640
},
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+
},
26402649
/* WCH CH382 2S1P card (16850 clone) */
26412650
{
26422651
.vendor = PCIE_VENDOR_ID_WCH,
@@ -2955,6 +2964,7 @@ enum pci_board_num_t {
29552964
pbn_fintek_4,
29562965
pbn_fintek_8,
29572966
pbn_fintek_12,
2967+
pbn_wch382_2,
29582968
pbn_wch384_4,
29592969
pbn_pericom_PI7C9X7951,
29602970
pbn_pericom_PI7C9X7952,
@@ -3775,6 +3785,13 @@ static struct pciserial_board pci_boards[] = {
37753785
.base_baud = 115200,
37763786
.first_offset = 0x40,
37773787
},
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+
},
37783795
[pbn_wch384_4] = {
37793796
.flags = FL_BASE0,
37803797
.num_ports = 4,
@@ -5574,6 +5591,10 @@ static struct pci_device_id serial_pci_tbl[] = {
55745591
PCI_ANY_ID, PCI_ANY_ID,
55755592
0, 0, pbn_b0_bt_2_115200 },
55765593

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+
55775598
{ PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S,
55785599
PCI_ANY_ID, PCI_ANY_ID,
55795600
0, 0, pbn_wch384_4 },

drivers/tty/serial/omap-serial.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ serial_omap_type(struct uart_port *port)
11651165

11661166
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
11671167

1168-
static void wait_for_xmitr(struct uart_omap_port *up)
1168+
static void __maybe_unused wait_for_xmitr(struct uart_omap_port *up)
11691169
{
11701170
unsigned int status, tmout = 10000;
11711171

@@ -1343,7 +1343,7 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up)
13431343

13441344
/* Enable or disable the rs485 support */
13451345
static int
1346-
serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
1346+
serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
13471347
{
13481348
struct uart_omap_port *up = to_uart_omap_port(port);
13491349
unsigned int mode;
@@ -1356,8 +1356,12 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
13561356
up->ier = 0;
13571357
serial_out(up, UART_IER, 0);
13581358

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+
13591363
/* store new config */
1360-
port->rs485 = *rs485conf;
1364+
port->rs485 = *rs485;
13611365

13621366
/*
13631367
* Just as a precaution, only allow rs485

drivers/tty/tty_io.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,13 +2066,12 @@ static int tty_open(struct inode *inode, struct file *filp)
20662066
if (tty) {
20672067
mutex_unlock(&tty_mutex);
20682068
retval = tty_lock_interruptible(tty);
2069+
tty_kref_put(tty); /* drop kref from tty_driver_lookup_tty() */
20692070
if (retval) {
20702071
if (retval == -EINTR)
20712072
retval = -ERESTARTSYS;
20722073
goto err_unref;
20732074
}
2074-
/* safe to drop the kref from tty_driver_lookup_tty() */
2075-
tty_kref_put(tty);
20762075
retval = tty_reopen(tty);
20772076
if (retval < 0) {
20782077
tty_unlock(tty);

drivers/tty/tty_mutex.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@ EXPORT_SYMBOL(tty_lock);
2121

2222
int tty_lock_interruptible(struct tty_struct *tty)
2323
{
24+
int ret;
25+
2426
if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
2527
return -EIO;
2628
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;
2833
}
2934

3035
void __lockfunc tty_unlock(struct tty_struct *tty)

fs/devpts/inode.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,26 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
575575
mutex_unlock(&allocated_ptys_lock);
576576
}
577577

578+
/*
579+
* pty code needs to hold extra references in case of last /dev/tty close
580+
*/
581+
582+
void 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+
590+
void 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+
578598
/**
579599
* devpts_pty_new -- create a new inode in /dev/pts/
580600
* @ptmx_inode: inode of the master

include/linux/devpts_fs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
int devpts_new_index(struct inode *ptmx_inode);
2121
void devpts_kill_index(struct inode *ptmx_inode, int idx);
22+
void devpts_add_ref(struct inode *ptmx_inode);
23+
void devpts_del_ref(struct inode *ptmx_inode);
2224
/* mknod in devpts */
2325
struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
2426
void *priv);
@@ -32,6 +34,8 @@ void devpts_pty_kill(struct inode *inode);
3234
/* Dummy stubs in the no-pty case */
3335
static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
3436
static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
37+
static inline void devpts_add_ref(struct inode *ptmx_inode) { }
38+
static inline void devpts_del_ref(struct inode *ptmx_inode) { }
3539
static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
3640
dev_t device, int index, void *priv)
3741
{

0 commit comments

Comments
 (0)