lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 17 Mar 2017 13:56:54 +0300
From:   Cyrill Gorcunov <gorcunov@...il.com>
To:     LKML <linux-kernel@...r.kernel.org>
Cc:     Andrey Vagin <avagin@...nvz.org>,
        Pavel Emelyanov <xemul@...tuozzo.com>,
        "Eric W. Biederman" <ebiederm@...ssion.com>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        Jiri Slaby <jslaby@...e.com>, "H. Peter Anvin" <hpa@...or.com>,
        Andrew Morton <akpm@...uxfoundation.org>
Subject: [RFC] tty: pty -- Add ability to setup next pty number for ptmx open

When we restore PTY terminals we do iterate over open() calls to reach
the index used at checkpoint time (say application opened a number of
terminals, then closed all other except last one) which of course very
inconvenient.

The problem get more notable in scope of controlling terminal represented
by /dev/tty device: current CRIU restore scheme is lazy, we don't open
files immedeately after the forks but rather defer until the whole
process tree is created, then every process opens own files in async
way and in result /dev/tty is not propagated into children because
it is not yet opened.

Both problems can be solved via criu itself but will require very
much efforts. So I would be very happy if we can open desired PTY
peer with index needed in one call instead. Which would allow us:

 - open a sole control terminal right after the fork and
   propagate it automatically into children

 - drop out our open(/dev/ptmx) sequence to reach index needed,
   improving performance and shrinking code

The API in the patch is trivial -- one have to open(/dev/ptmx)
and automatically get index 0, then simply do
ioctl(fd, TIOCSPTN, index) and next open(/dev/ptmx)
will return pair with point number requested.

CC: Andrey Vagin <avagin@...nvz.org>
CC: Pavel Emelyanov <xemul@...tuozzo.com>
CC: "Eric W. Biederman" <ebiederm@...ssion.com>
CC: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
CC: Jiri Slaby <jslaby@...e.com>
CC: "H. Peter Anvin" <hpa@...or.com>
CC: Andrew Morton <akpm@...uxfoundation.org>
Signed-off-by: Cyrill Gorcunov <gorcunov@...nvz.org>
---
 drivers/tty/pty.c                 |   14 ++++++++++++++
 fs/devpts/inode.c                 |   22 ++++++++++++++++++++--
 include/linux/devpts_fs.h         |    1 +
 include/uapi/asm-generic/ioctls.h |    1 +
 4 files changed, 36 insertions(+), 2 deletions(-)

Index: linux-ml.git/drivers/tty/pty.c
===================================================================
--- linux-ml.git.orig/drivers/tty/pty.c
+++ linux-ml.git/drivers/tty/pty.c
@@ -593,6 +593,18 @@ static inline void legacy_pty_init(void)
 
 static struct cdev ptmx_cdev;
 
+static int pty_set_next_ptn(struct tty_struct *tty, int next_ptn)
+{
+	if (tty->driver->subtype == PTY_TYPE_MASTER) {
+		struct pts_fs_info *fsi;
+
+		fsi = tty->driver_data;
+		return devpts_set_next_index(fsi, next_ptn);
+	}
+
+	return -ENOIOCTLCMD;
+}
+
 static int pty_unix98_ioctl(struct tty_struct *tty,
 			    unsigned int cmd, unsigned long arg)
 {
@@ -607,6 +619,8 @@ static int pty_unix98_ioctl(struct tty_s
 		return pty_get_pktmode(tty, (int __user *)arg);
 	case TIOCGPTN: /* Get PT Number */
 		return put_user(tty->index, (unsigned int __user *)arg);
+	case TIOCSPTN:
+		return pty_set_next_ptn(tty, (unsigned int)arg);
 	case TIOCSIG:    /* Send signal to other side of pty */
 		return pty_signal(tty, (int) arg);
 	}
Index: linux-ml.git/fs/devpts/inode.c
===================================================================
--- linux-ml.git.orig/fs/devpts/inode.c
+++ linux-ml.git/fs/devpts/inode.c
@@ -126,6 +126,7 @@ struct pts_fs_info {
 	struct pts_mount_opts mount_opts;
 	struct super_block *sb;
 	struct dentry *ptmx_dentry;
+	int pty_next_idx;
 };
 
 static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
@@ -486,7 +487,8 @@ retry:
 		return -ENOSPC;
 	}
 
-	ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
+	ida_ret = ida_get_new_above(&fsi->allocated_ptys,
+				    fsi->pty_next_idx, &index);
 	if (ida_ret < 0) {
 		mutex_unlock(&allocated_ptys_lock);
 		if (ida_ret == -EAGAIN)
@@ -494,7 +496,9 @@ retry:
 		return -EIO;
 	}
 
-	if (index >= fsi->mount_opts.max) {
+	if (index >= fsi->mount_opts.max ||
+	    (fsi->pty_next_idx &&
+	     fsi->pty_next_idx != index)) {
 		ida_remove(&fsi->allocated_ptys, index);
 		mutex_unlock(&allocated_ptys_lock);
 		return -ENOSPC;
@@ -512,6 +516,20 @@ void devpts_kill_index(struct pts_fs_inf
 	mutex_unlock(&allocated_ptys_lock);
 }
 
+int devpts_set_next_index(struct pts_fs_info *fsi, int next_idx)
+{
+	int ret = 0;
+
+	mutex_lock(&allocated_ptys_lock);
+	if (fsi->mount_opts.max > next_idx && next_idx >= 0)
+		fsi->pty_next_idx = next_idx;
+	else
+		ret = -ENOSPC;
+	mutex_unlock(&allocated_ptys_lock);
+
+	return ret;
+}
+
 /**
  * devpts_pty_new -- create a new inode in /dev/pts/
  * @ptmx_inode: inode of the master
Index: linux-ml.git/include/linux/devpts_fs.h
===================================================================
--- linux-ml.git.orig/include/linux/devpts_fs.h
+++ linux-ml.git/include/linux/devpts_fs.h
@@ -24,6 +24,7 @@ void devpts_release(struct pts_fs_info *
 
 int devpts_new_index(struct pts_fs_info *);
 void devpts_kill_index(struct pts_fs_info *, int);
+int devpts_set_next_index(struct pts_fs_info *, int);
 
 /* mknod in devpts */
 struct dentry *devpts_pty_new(struct pts_fs_info *, int, void *);
Index: linux-ml.git/include/uapi/asm-generic/ioctls.h
===================================================================
--- linux-ml.git.orig/include/uapi/asm-generic/ioctls.h
+++ linux-ml.git/include/uapi/asm-generic/ioctls.h
@@ -68,6 +68,7 @@
 #define TIOCGPTN	_IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
+#define TIOCSPTN	_IOW('T', 0x33, unsigned int) /* Set next Pty Number (of pty-mux device) */
 #define TCGETX		0x5432 /* SYS5 TCGETX compatibility */
 #define TCSETX		0x5433
 #define TCSETXF		0x5434

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ