diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h index f30c94ae1bdb19499af9b21c0006f06f6756d43f..ff67b8373bf78bb24a72df561390236842707a6a 100644 --- a/arch/alpha/include/uapi/asm/ioctls.h +++ b/arch/alpha/include/uapi/asm/ioctls.h @@ -100,6 +100,7 @@ #define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCGPTPEER _IOR('T', 0x41, int) /* Safely open the slave */ #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h index 740219c2c8943df14abe39c7e3dde6c4d2149f0d..68e19b689a00c4d783cdde376ca40c95a48c3f3c 100644 --- a/arch/mips/include/uapi/asm/ioctls.h +++ b/arch/mips/include/uapi/asm/ioctls.h @@ -91,6 +91,7 @@ #define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCGPTPEER _IOR('T', 0x41, int) /* Safely open the slave */ /* I hope the range from 0x5480 on is free ... */ #define TIOCSCTTY 0x5480 /* become controlling tty */ diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h index b6572f051b6739d5aa94035224e5928ca3a470cf..674c68a5bbd035c86bee42834d010ba20eb06464 100644 --- a/arch/parisc/include/uapi/asm/ioctls.h +++ b/arch/parisc/include/uapi/asm/ioctls.h @@ -60,6 +60,7 @@ #define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCGPTPEER _IOR('T', 0x41, int) /* Safely open the slave */ #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ #define FIOCLEX 0x5451 diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h index 49a25796a61af05b6d61c27bf9e507977711c3ef..bfd609a3e928f8b8536567e4e030cf8ff05643ff 100644 --- a/arch/powerpc/include/uapi/asm/ioctls.h +++ b/arch/powerpc/include/uapi/asm/ioctls.h @@ -100,6 +100,7 @@ #define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCGPTPEER _IOR('T', 0x41, int) /* Safely open the slave */ #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h index c9903e56ccf4381b99bdf6f042e70af1882841f9..eec7901e9e658b18e0eadeeb2af65966cc15993d 100644 --- a/arch/sh/include/uapi/asm/ioctls.h +++ b/arch/sh/include/uapi/asm/ioctls.h @@ -93,6 +93,7 @@ #define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCGPTPEER _IOR('T', 0x41, int) /* Safely open the slave */ #define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */ #define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */ diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h index 06b3f6c3bb9aa353362cc90acf2585b11227dd1d..6d27398632eacd22a72e0437ea57d1c048930d11 100644 --- a/arch/sparc/include/uapi/asm/ioctls.h +++ b/arch/sparc/include/uapi/asm/ioctls.h @@ -27,7 +27,7 @@ #define TIOCGRS485 _IOR('T', 0x41, struct serial_rs485) #define TIOCSRS485 _IOWR('T', 0x42, struct serial_rs485) -/* Note that all the ioctls that are not available in Linux have a +/* Note that all the ioctls that are not available in Linux have a * double underscore on the front to: a) avoid some programs to * think we support some ioctls under Linux (autoconfiguration stuff) */ @@ -88,6 +88,7 @@ #define TIOCGPTN _IOR('t', 134, unsigned int) /* Get Pty Number */ #define TIOCSPTLCK _IOW('t', 135, int) /* Lock/unlock PTY */ #define TIOCSIG _IOW('t', 136, int) /* Generate signal on Pty slave */ +#define TIOCGPTPEER _IOR('t', 137, int) /* Safely open the slave */ /* Little f */ #define FIOCLEX _IO('f', 1) diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h index 518954e74e6d5e49e77c14a6eecb104319019edd..98b004e24e8523b735d60937c56e22b2b0f7d2bd 100644 --- a/arch/xtensa/include/uapi/asm/ioctls.h +++ b/arch/xtensa/include/uapi/asm/ioctls.h @@ -105,6 +105,7 @@ #define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCGPTPEER _IOR('T', 0x41, int) /* Safely open the slave */ #define TIOCSERCONFIG _IO('T', 83) #define TIOCSERGWILD _IOR('T', 84, int) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 2a6bd9ae3f8b2f341fd4d3ddfe0af39cf6478f9d..d1399aac05a17e96ead10d5bd616a5a780ce9237 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #undef TTY_DEBUG_HANGUP #ifdef TTY_DEBUG_HANGUP @@ -66,8 +69,13 @@ static void pty_close(struct tty_struct *tty, struct file *filp) #ifdef CONFIG_UNIX98_PTYS if (tty->driver == ptm_driver) { mutex_lock(&devpts_mutex); - if (tty->link->driver_data) - devpts_pty_kill(tty->link->driver_data); + if (tty->link->driver_data) { + struct path *path = tty->link->driver_data; + + devpts_pty_kill(path->dentry); + path_put(path); + kfree(path); + } mutex_unlock(&devpts_mutex); } #endif @@ -440,6 +448,48 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, return retval; } +/** + * pty_open_peer - open the peer of a pty + * @tty: the peer of the pty being opened + * + * Open the cached dentry in tty->link, providing a safe way for userspace + * to get the slave end of a pty (where they have the master fd and cannot + * access or trust the mount namespace /dev/pts was mounted inside). + */ +static struct file *pty_open_peer(struct tty_struct *tty, int flags) +{ + if (tty->driver->subtype != PTY_TYPE_MASTER) + return ERR_PTR(-EIO); + return dentry_open(tty->link->driver_data, flags, current_cred()); +} + +static int pty_get_peer(struct tty_struct *tty, int flags) +{ + int fd = -1; + struct file *filp = NULL; + int retval = -EINVAL; + + fd = get_unused_fd_flags(0); + if (fd < 0) { + retval = fd; + goto err; + } + + filp = pty_open_peer(tty, flags); + if (IS_ERR(filp)) { + retval = PTR_ERR(filp); + goto err_put; + } + + fd_install(fd, filp); + return fd; + +err_put: + put_unused_fd(fd); +err: + return retval; +} + static void pty_cleanup(struct tty_struct *tty) { tty_port_put(tty->port); @@ -613,6 +663,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, return pty_get_pktmode(tty, (int __user *)arg); case TIOCGPTN: /* Get PT Number */ return put_user(tty->index, (unsigned int __user *)arg); + case TIOCGPTPEER: /* Open the other end */ + return pty_get_peer(tty, (int) arg); case TIOCSIG: /* Send signal to other side of pty */ return pty_signal(tty, (int) arg); } @@ -740,6 +792,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) { struct pts_fs_info *fsi; struct tty_struct *tty; + struct path *pts_path; struct dentry *dentry; int retval; int index; @@ -793,16 +846,26 @@ static int ptmx_open(struct inode *inode, struct file *filp) retval = PTR_ERR(dentry); goto err_release; } - tty->link->driver_data = dentry; + /* We need to cache a fake path for TIOCGPTPEER. */ + pts_path = kmalloc(sizeof(struct path), GFP_KERNEL); + if (!pts_path) + goto err_release; + pts_path->mnt = filp->f_path.mnt; + pts_path->dentry = dentry; + path_get(pts_path); + tty->link->driver_data = pts_path; retval = ptm_driver->ops->open(tty, filp); if (retval) - goto err_release; + goto err_path_put; tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); tty_unlock(tty); return 0; +err_path_put: + path_put(pts_path); + kfree(pts_path); err_release: tty_unlock(tty); // This will also put-ref the fsi diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h index 143dacbb7d9ae452bc8e27d56d4c7f8485ac8acc..06d5f7ddf84e73bc08e1719c1c97795ada561fff 100644 --- a/include/uapi/asm-generic/ioctls.h +++ b/include/uapi/asm-generic/ioctls.h @@ -77,6 +77,7 @@ #define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCGPTPEER _IOR('T', 0x41, int) /* Safely open the slave */ #define FIONCLEX 0x5450 #define FIOCLEX 0x5451