diff options
Diffstat (limited to 'drivers/tty/pty.c')
| -rw-r--r-- | drivers/tty/pty.c | 21 | 
1 files changed, 20 insertions, 1 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)  /* this is called once with whichever end is closed last */  static void pty_unix98_shutdown(struct tty_struct *tty)  { -	devpts_kill_index(tty->driver_data, tty->index); +	struct inode *ptmx_inode; + +	if (tty->driver->subtype == PTY_TYPE_MASTER) +		ptmx_inode = tty->driver_data; +	else +		ptmx_inode = tty->link->driver_data; +	devpts_kill_index(ptmx_inode, tty->index); +	devpts_del_ref(ptmx_inode);  }  static const struct tty_operations ptm_unix98_ops = { @@ -773,6 +780,18 @@ static int ptmx_open(struct inode *inode, struct file *filp)  	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */  	tty->driver_data = inode; +	/* +	 * In the case where all references to ptmx inode are dropped and we +	 * still have /dev/tty opened pointing to the master/slave pair (ptmx +	 * is closed/released before /dev/tty), we must make sure that the inode +	 * is still valid when we call the final pty_unix98_shutdown, thus we +	 * hold an additional reference to the ptmx inode. For the same /dev/tty +	 * last close case, we also need to make sure the super_block isn't +	 * destroyed (devpts instance unmounted), before /dev/tty is closed and +	 * on its release devpts_kill_index is called. +	 */ +	devpts_add_ref(inode); +  	tty_add_file(tty, filp);  	slave_inode = devpts_pty_new(inode, | 
