aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/pty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/pty.c')
-rw-r--r--drivers/tty/pty.c64
1 files changed, 27 insertions, 37 deletions
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 284749fb0f6b..a6d5164c33a9 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -69,13 +69,8 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
69#ifdef CONFIG_UNIX98_PTYS 69#ifdef CONFIG_UNIX98_PTYS
70 if (tty->driver == ptm_driver) { 70 if (tty->driver == ptm_driver) {
71 mutex_lock(&devpts_mutex); 71 mutex_lock(&devpts_mutex);
72 if (tty->link->driver_data) { 72 if (tty->link->driver_data)
73 struct path *path = tty->link->driver_data; 73 devpts_pty_kill(tty->link->driver_data);
74
75 devpts_pty_kill(path->dentry);
76 path_put(path);
77 kfree(path);
78 }
79 mutex_unlock(&devpts_mutex); 74 mutex_unlock(&devpts_mutex);
80 } 75 }
81#endif 76#endif
@@ -607,25 +602,24 @@ static inline void legacy_pty_init(void) { }
607static struct cdev ptmx_cdev; 602static struct cdev ptmx_cdev;
608 603
609/** 604/**
610 * pty_open_peer - open the peer of a pty 605 * ptm_open_peer - open the peer of a pty
611 * @tty: the peer of the pty being opened 606 * @master: the open struct file of the ptmx device node
607 * @tty: the master of the pty being opened
608 * @flags: the flags for open
612 * 609 *
613 * Open the cached dentry in tty->link, providing a safe way for userspace 610 * Provide a race free way for userspace to open the slave end of a pty
614 * to get the slave end of a pty (where they have the master fd and cannot 611 * (where they have the master fd and cannot access or trust the mount
615 * access or trust the mount namespace /dev/pts was mounted inside). 612 * namespace /dev/pts was mounted inside).
616 */ 613 */
617static struct file *pty_open_peer(struct tty_struct *tty, int flags) 614int ptm_open_peer(struct file *master, struct tty_struct *tty, int flags)
618{
619 if (tty->driver->subtype != PTY_TYPE_MASTER)
620 return ERR_PTR(-EIO);
621 return dentry_open(tty->link->driver_data, flags, current_cred());
622}
623
624static int pty_get_peer(struct tty_struct *tty, int flags)
625{ 615{
626 int fd = -1; 616 int fd = -1;
627 struct file *filp = NULL; 617 struct file *filp;
628 int retval = -EINVAL; 618 int retval = -EINVAL;
619 struct path path;
620
621 if (tty->driver != ptm_driver)
622 return -EIO;
629 623
630 fd = get_unused_fd_flags(0); 624 fd = get_unused_fd_flags(0);
631 if (fd < 0) { 625 if (fd < 0) {
@@ -633,7 +627,16 @@ static int pty_get_peer(struct tty_struct *tty, int flags)
633 goto err; 627 goto err;
634 } 628 }
635 629
636 filp = pty_open_peer(tty, flags); 630 /* Compute the slave's path */
631 path.mnt = devpts_mntget(master, tty->driver_data);
632 if (IS_ERR(path.mnt)) {
633 retval = PTR_ERR(path.mnt);
634 goto err_put;
635 }
636 path.dentry = tty->link->driver_data;
637
638 filp = dentry_open(&path, flags, current_cred());
639 mntput(path.mnt);
637 if (IS_ERR(filp)) { 640 if (IS_ERR(filp)) {
638 retval = PTR_ERR(filp); 641 retval = PTR_ERR(filp);
639 goto err_put; 642 goto err_put;
@@ -662,8 +665,6 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
662 return pty_get_pktmode(tty, (int __user *)arg); 665 return pty_get_pktmode(tty, (int __user *)arg);
663 case TIOCGPTN: /* Get PT Number */ 666 case TIOCGPTN: /* Get PT Number */
664 return put_user(tty->index, (unsigned int __user *)arg); 667 return put_user(tty->index, (unsigned int __user *)arg);
665 case TIOCGPTPEER: /* Open the other end */
666 return pty_get_peer(tty, (int) arg);
667 case TIOCSIG: /* Send signal to other side of pty */ 668 case TIOCSIG: /* Send signal to other side of pty */
668 return pty_signal(tty, (int) arg); 669 return pty_signal(tty, (int) arg);
669 } 670 }
@@ -791,7 +792,6 @@ static int ptmx_open(struct inode *inode, struct file *filp)
791{ 792{
792 struct pts_fs_info *fsi; 793 struct pts_fs_info *fsi;
793 struct tty_struct *tty; 794 struct tty_struct *tty;
794 struct path *pts_path;
795 struct dentry *dentry; 795 struct dentry *dentry;
796 int retval; 796 int retval;
797 int index; 797 int index;
@@ -845,26 +845,16 @@ static int ptmx_open(struct inode *inode, struct file *filp)
845 retval = PTR_ERR(dentry); 845 retval = PTR_ERR(dentry);
846 goto err_release; 846 goto err_release;
847 } 847 }
848 /* We need to cache a fake path for TIOCGPTPEER. */ 848 tty->link->driver_data = dentry;
849 pts_path = kmalloc(sizeof(struct path), GFP_KERNEL);
850 if (!pts_path)
851 goto err_release;
852 pts_path->mnt = filp->f_path.mnt;
853 pts_path->dentry = dentry;
854 path_get(pts_path);
855 tty->link->driver_data = pts_path;
856 849
857 retval = ptm_driver->ops->open(tty, filp); 850 retval = ptm_driver->ops->open(tty, filp);
858 if (retval) 851 if (retval)
859 goto err_path_put; 852 goto err_release;
860 853
861 tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); 854 tty_debug_hangup(tty, "opening (count=%d)\n", tty->count);
862 855
863 tty_unlock(tty); 856 tty_unlock(tty);
864 return 0; 857 return 0;
865err_path_put:
866 path_put(pts_path);
867 kfree(pts_path);
868err_release: 858err_release:
869 tty_unlock(tty); 859 tty_unlock(tty);
870 // This will also put-ref the fsi 860 // This will also put-ref the fsi