linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: ebiederm@xmission.com (Eric W. Biederman)
To: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Andy Lutomirski <luto@amacapital.net>,
	security@debian.org, "security\@kernel.org" <security@kernel.org>,
	Al Viro <viro@zeniv.linux.org.uk>,
	"security\@ubuntu.com \>\> security" <security@ubuntu.com>,
	Serge Hallyn <serge.hallyn@ubuntu.com>, Willy Tarreau <w@1wt.eu>,
	Aurelien Jarno <aurelien@aurel32.net>,
	One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>,
	Jann Horn <jann@thejh.net>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Jiri Slaby <jslaby@suse.com>, Florian Weimer <fw@deneb.enyo.de>,
	Konstantin Khlebnikov <koct9i@gmail.com>
Subject: [PATCH tty-next] devpts: Make each mount of devpts an independent filesystem.
Date: Thu, 02 Jun 2016 10:29:47 -0500	[thread overview]
Message-ID: <878tyn4nis.fsf_-_@x220.int.ebiederm.org> (raw)
In-Reply-To: <20160506195459.GB27790@kroah.com> (Greg KH's message of "Fri, 6 May 2016 15:54:59 -0400")


The /dev/ptmx device node is changed to lookup the directory entry
"pts" in the same directory as the /dev/ptmx device node was opened
in.  If there is a "pts" entry and that entry is a devpts filesystem
/dev/ptmx uses that filesystem.  Otherwise the open of /dev/ptmx
fails.

The DEVPTS_MULTIPLE_INSTANCES configuration option is removed,
so that userspace can now safely depend on each mount of devpts
creating a new instance of the filesystem.

Each mount of devpts is now a separate and equal filesystem.

Reserved ttys are now available to all instances of devpts where the
mounter is in the initial mount namespace.

A new vfs helper path_pts is introduced that finds a directory entry
named "pts" in the directory of the passed in path, and changes the
passed in path to point to it.  The helper path_pts uses a function
path_parent_directory that was factored out of follow_dotdot.

In the implementation of devpts:
- devpts_mnt is killed as it is no longer meaningful if all
  mounts of devpts are equal.
- pts_sb_from_inode is replaced by just inode->i_sb as all
  cached inodes in the tty layer are now from the devpts
  filesystem.
- devpts_add_ref is rolled into the new function devpts_ptmx.
  And the unnecessary inode hold is removed.
- devpts_del_ref is renamed devpts_release and reduced
  to just a deacrivate_super.
- The newinstance mount option continues to be accepted but is now ignored.

In devpts_fs.h definitions for when !CONFIG_UNIX98_PTYS are removed
as they are never used.

Documentation/filesystems/devices.txt is updated to describe
the current situation.

This has been verified to work properly on openwrt-15.05, centos5,
centos6, centos7, debian-6.0.2, debian-7.9, debian-8.2,
ubuntu-14.04.3, ubuntu-15.10, fedora23, magia-5, mint-17.3,
opensuse-42.1, slackware-14.1, gentoo-20151225 (13.0?),
archlinux-2015-12-01.  With the caveat that on centos6 and on
slackware-14.1 that there wind up being two instances of the devpts
filesystem mounted on /dev/pts, the lower copy does not end up getting
used.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 Documentation/filesystems/devpts.txt | 145 +++-----------------------
 drivers/tty/Kconfig                  |  11 --
 drivers/tty/pty.c                    |  15 +--
 fs/devpts/inode.c                    | 191 ++++++++++-------------------------
 fs/namei.c                           |  49 +++++++--
 include/linux/devpts_fs.h            |   9 +-
 include/linux/namei.h                |   2 +
 7 files changed, 126 insertions(+), 296 deletions(-)

diff --git a/Documentation/filesystems/devpts.txt b/Documentation/filesystems/devpts.txt
index 30d2fcb32f72..9f94fe276dea 100644
--- a/Documentation/filesystems/devpts.txt
+++ b/Documentation/filesystems/devpts.txt
@@ -1,141 +1,26 @@
+Each mount of the devpts filesystem is now distinct such that ptys
+and their indicies allocated in one mount are independent from ptys
+and their indicies in all other mounts.
 
-To support containers, we now allow multiple instances of devpts filesystem,
-such that indices of ptys allocated in one instance are independent of indices
-allocated in other instances of devpts.
+All mounts of the devpts filesystem now create a /dev/pts/ptmx node
+with permissions 0000.
 
-To preserve backward compatibility, this support for multiple instances is
-enabled only if:
+To retain backwards compatibility the a ptmx device node (aka any node
+created with "mknod name c 5 2") when opened will look for an instance
+of devpts under the name "pts" in the same directory as the ptmx device
+node.
 
-	- CONFIG_DEVPTS_MULTIPLE_INSTANCES=y, and
-	- '-o newinstance' mount option is specified while mounting devpts
-
-IOW, devpts now supports both single-instance and multi-instance semantics.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, there is no change in behavior and
-this referred to as the "legacy" mode. In this mode, the new mount options
-(-o newinstance and -o ptmxmode) will be ignored with a 'bogus option' message
-on console.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and devpts is mounted without the
-'newinstance' option (as in current start-up scripts) the new mount binds
-to the initial kernel mount of devpts. This mode is referred to as the
-'single-instance' mode and the current, single-instance semantics are
-preserved, i.e PTYs are common across the system.
-
-The only difference between this single-instance mode and the legacy mode
-is the presence of new, '/dev/pts/ptmx' node with permissions 0000, which
-can safely be ignored.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and 'newinstance' option is specified,
-the mount is considered to be in the multi-instance mode and a new instance
-of the devpts fs is created. Any ptys created in this instance are independent
-of ptys in other instances of devpts. Like in the single-instance mode, the
-/dev/pts/ptmx node is present. To effectively use the multi-instance mode,
-open of /dev/ptmx must be a redirected to '/dev/pts/ptmx' using a symlink or
-bind-mount.
-
-Eg: A container startup script could do the following:
-
-	$ chmod 0666 /dev/pts/ptmx
-	$ rm /dev/ptmx
-	$ ln -s pts/ptmx /dev/ptmx
-	$ ns_exec -cm /bin/bash
-
-	# We are now in new container
-
-	$ umount /dev/pts
-	$ mount -t devpts -o newinstance lxcpts /dev/pts
-	$ sshd -p 1234
-
-where 'ns_exec -cm /bin/bash' calls clone() with CLONE_NEWNS flag and execs
-/bin/bash in the child process.  A pty created by the sshd is not visible in
-the original mount of /dev/pts.
+As an option instead of placing a /dev/ptmx device node at /dev/ptmx
+it is possible to place a symlink to /dev/pts/ptmx at /dev/ptmx or
+to bind mount /dev/ptx/ptmx to /dev/ptmx.  If you opt for using
+the devpts filesystem in this manner devpts should be mounted with
+the ptmxmode=0666, or chmod 0666 /dev/pts/ptmx should be called.
 
 Total count of pty pairs in all instances is limited by sysctls:
 kernel.pty.max = 4096		- global limit
-kernel.pty.reserve = 1024	- reserve for initial instance
+kernel.pty.reserve = 1024	- reserved for filesystems mounted from the initial mount namespace
 kernel.pty.nr			- current count of ptys
 
 Per-instance limit could be set by adding mount option "max=<count>".
 This feature was added in kernel 3.4 together with sysctl kernel.pty.reserve.
 In kernels older than 3.4 sysctl kernel.pty.max works as per-instance limit.
-
-User-space changes
-------------------
-
-In multi-instance mode (i.e '-o newinstance' mount option is specified at least
-once), following user-space issues should be noted.
-
-1. If -o newinstance mount option is never used, /dev/pts/ptmx can be ignored
-   and no change is needed to system-startup scripts.
-
-2. To effectively use multi-instance mode (i.e -o newinstance is specified)
-   administrators or startup scripts should "redirect" open of /dev/ptmx to
-   /dev/pts/ptmx using either a bind mount or symlink.
-
-	$ mount -t devpts -o newinstance devpts /dev/pts
-
-   followed by either
-
-	$ rm /dev/ptmx
-	$ ln -s pts/ptmx /dev/ptmx
-	$ chmod 666 /dev/pts/ptmx
-   or
-	$ mount -o bind /dev/pts/ptmx /dev/ptmx
-
-3. The '/dev/ptmx -> pts/ptmx' symlink is the preferred method since it
-   enables better error-reporting and treats both single-instance and
-   multi-instance mounts similarly.
-
-   But this method requires that system-startup scripts set the mode of
-   /dev/pts/ptmx correctly (default mode is 0000). The scripts can set the
-   mode by, either
-
-   	- adding ptmxmode mount option to devpts entry in /etc/fstab, or
-	- using 'chmod 0666 /dev/pts/ptmx'
-
-4. If multi-instance mode mount is needed for containers, but the system
-   startup scripts have not yet been updated, container-startup scripts
-   should bind mount /dev/ptmx to /dev/pts/ptmx to avoid breaking single-
-   instance mounts.
-
-   Or, in general, container-startup scripts should use:
-
-	mount -t devpts -o newinstance -o ptmxmode=0666 devpts /dev/pts
-	if [ ! -L /dev/ptmx ]; then
-		mount -o bind /dev/pts/ptmx /dev/ptmx
-	fi
-
-   When all devpts mounts are multi-instance, /dev/ptmx can permanently be
-   a symlink to pts/ptmx and the bind mount can be ignored.
-
-5. A multi-instance mount that is not accompanied by the /dev/ptmx to
-   /dev/pts/ptmx redirection would result in an unusable/unreachable pty.
-
-	mount -t devpts -o newinstance lxcpts /dev/pts
-
-   immediately followed by:
-
-	open("/dev/ptmx")
-
-    would create a pty, say /dev/pts/7, in the initial kernel mount.
-    But /dev/pts/7 would be invisible in the new mount.
-
-6. The permissions for /dev/pts/ptmx node should be specified when mounting
-   /dev/pts, using the '-o ptmxmode=%o' mount option (default is 0000).
-
-	mount -t devpts -o newinstance -o ptmxmode=0644 devpts /dev/pts
-
-   The permissions can be later be changed as usual with 'chmod'.
-
-	chmod 666 /dev/pts/ptmx
-
-7. A mount of devpts without the 'newinstance' option results in binding to
-   initial kernel mount.  This behavior while preserving legacy semantics,
-   does not provide strict isolation in a container environment. i.e by
-   mounting devpts without the 'newinstance' option, a container could
-   get visibility into the 'host' or root container's devpts.
-   
-   To workaround this and have strict isolation, all mounts of devpts,
-   including the mount in the root container, should use the newinstance
-   option.
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index 82c4d2e45319..95103054c0e4 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -120,17 +120,6 @@ config UNIX98_PTYS
 	  All modern Linux systems use the Unix98 ptys.  Say Y unless
 	  you're on an embedded system and want to conserve memory.
 
-config DEVPTS_MULTIPLE_INSTANCES
-	bool "Support multiple instances of devpts"
-	depends on UNIX98_PTYS
-	default n
-	---help---
-	  Enable support for multiple instances of devpts filesystem.
-	  If you want to have isolated PTY namespaces (eg: in containers),
-	  say Y here.  Otherwise, say N. If enabled, each mount of devpts
-	  filesystem with the '-o newinstance' option will create an
-	  independent PTY namespace.
-
 config LEGACY_PTYS
 	bool "Legacy (BSD) PTY support"
 	default y
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index dd4b8417e7f4..f856c4544eea 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -668,7 +668,7 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
 	else
 		fsi = tty->link->driver_data;
 	devpts_kill_index(fsi, tty->index);
-	devpts_put_ref(fsi);
+	devpts_release(fsi);
 }
 
 static const struct tty_operations ptm_unix98_ops = {
@@ -733,10 +733,11 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 	if (retval)
 		return retval;
 
-	fsi = devpts_get_ref(inode, filp);
-	retval = -ENODEV;
-	if (!fsi)
+	fsi = devpts_acquire(filp);
+	if (IS_ERR(fsi)) {
+		retval = PTR_ERR(fsi);
 		goto out_free_file;
+	}
 
 	/* find a device that is not in use. */
 	mutex_lock(&devpts_mutex);
@@ -745,7 +746,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 
 	retval = index;
 	if (index < 0)
-		goto out_put_ref;
+		goto out_put_fsi;
 
 
 	mutex_lock(&tty_mutex);
@@ -789,8 +790,8 @@ err_release:
 	return retval;
 out:
 	devpts_kill_index(fsi, index);
-out_put_ref:
-	devpts_put_ref(fsi);
+out_put_fsi:
+	devpts_release(fsi);
 out_free_file:
 	tty_free_file(filp);
 	return retval;
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 0b2954d7172d..37c134a132c7 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -95,8 +95,6 @@ static struct ctl_table pty_root_table[] = {
 
 static DEFINE_MUTEX(allocated_ptys_lock);
 
-static struct vfsmount *devpts_mnt;
-
 struct pts_mount_opts {
 	int setuid;
 	int setgid;
@@ -104,7 +102,7 @@ struct pts_mount_opts {
 	kgid_t   gid;
 	umode_t mode;
 	umode_t ptmxmode;
-	int newinstance;
+	int reserve;
 	int max;
 };
 
@@ -117,11 +115,9 @@ static const match_table_t tokens = {
 	{Opt_uid, "uid=%u"},
 	{Opt_gid, "gid=%u"},
 	{Opt_mode, "mode=%o"},
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
 	{Opt_ptmxmode, "ptmxmode=%o"},
 	{Opt_newinstance, "newinstance"},
 	{Opt_max, "max=%d"},
-#endif
 	{Opt_err, NULL}
 };
 
@@ -137,15 +133,48 @@ static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
 	return sb->s_fs_info;
 }
 
-static inline struct super_block *pts_sb_from_inode(struct inode *inode)
+struct pts_fs_info *devpts_acquire(struct file *filp)
 {
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
-	if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
-		return inode->i_sb;
-#endif
-	if (!devpts_mnt)
-		return NULL;
-	return devpts_mnt->mnt_sb;
+	struct pts_fs_info *result;
+	struct path path;
+	struct super_block *sb;
+	int err;
+
+	path = filp->f_path;
+	path_get(&path);
+
+	/* Has the devpts filesystem already been found? */
+	sb = path.mnt->mnt_sb;
+	if (sb->s_magic != DEVPTS_SUPER_MAGIC) {
+		/* Is a devpts filesystem at "pts" in the same directory? */
+		err = path_pts(&path);
+		if (err) {
+			result = ERR_PTR(err);
+			goto out;
+		}
+
+		/* Is the path the root of a devpts filesystem? */
+		result = ERR_PTR(-ENODEV);
+		sb = path.mnt->mnt_sb;
+		if ((sb->s_magic != DEVPTS_SUPER_MAGIC) ||
+		    (path.mnt->mnt_root != sb->s_root))
+			goto out;
+	}
+
+	/*
+	 * pty code needs to hold extra references in case of last /dev/tty close
+	 */
+	atomic_inc(&sb->s_active);
+	result = DEVPTS_SB(sb);
+
+out:
+	path_put(&path);
+	return result;
+}
+
+void devpts_release(struct pts_fs_info *fsi)
+{
+	deactivate_super(fsi->sb);
 }
 
 #define PARSE_MOUNT	0
@@ -154,9 +183,7 @@ static inline struct super_block *pts_sb_from_inode(struct inode *inode)
 /*
  * parse_mount_options():
  *	Set @opts to mount options specified in @data. If an option is not
- *	specified in @data, set it to its default value. The exception is
- *	'newinstance' option which can only be set/cleared on a mount (i.e.
- *	cannot be changed during remount).
+ *	specified in @data, set it to its default value.
  *
  * Note: @data may be NULL (in which case all options are set to default).
  */
@@ -174,9 +201,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
 	opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
 	opts->max     = NR_UNIX98_PTY_MAX;
 
-	/* newinstance makes sense only on initial mount */
+	/* Only allow instances mounted from the initial mount
+	 * namespace to tap the reserve pool of ptys.
+	 */
 	if (op == PARSE_MOUNT)
-		opts->newinstance = 0;
+		opts->reserve =
+			(current->nsproxy->mnt_ns == init_task.nsproxy->mnt_ns);
 
 	while ((p = strsep(&data, ",")) != NULL) {
 		substring_t args[MAX_OPT_ARGS];
@@ -211,16 +241,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
 				return -EINVAL;
 			opts->mode = option & S_IALLUGO;
 			break;
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
 		case Opt_ptmxmode:
 			if (match_octal(&args[0], &option))
 				return -EINVAL;
 			opts->ptmxmode = option & S_IALLUGO;
 			break;
 		case Opt_newinstance:
-			/* newinstance makes sense only on initial mount */
-			if (op == PARSE_MOUNT)
-				opts->newinstance = 1;
 			break;
 		case Opt_max:
 			if (match_int(&args[0], &option) ||
@@ -228,7 +254,6 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
 				return -EINVAL;
 			opts->max = option;
 			break;
-#endif
 		default:
 			pr_err("called with bogus options\n");
 			return -EINVAL;
@@ -238,7 +263,6 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
 	return 0;
 }
 
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
 static int mknod_ptmx(struct super_block *sb)
 {
 	int mode;
@@ -305,12 +329,6 @@ static void update_ptmx_mode(struct pts_fs_info *fsi)
 		inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
 	}
 }
-#else
-static inline void update_ptmx_mode(struct pts_fs_info *fsi)
-{
-	return;
-}
-#endif
 
 static int devpts_remount(struct super_block *sb, int *flags, char *data)
 {
@@ -344,11 +362,9 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root)
 		seq_printf(seq, ",gid=%u",
 			   from_kgid_munged(&init_user_ns, opts->gid));
 	seq_printf(seq, ",mode=%03o", opts->mode);
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
 	seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
 	if (opts->max < NR_UNIX98_PTY_MAX)
 		seq_printf(seq, ",max=%d", opts->max);
-#endif
 
 	return 0;
 }
@@ -410,40 +426,11 @@ fail:
 	return -ENOMEM;
 }
 
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
-static int compare_init_pts_sb(struct super_block *s, void *p)
-{
-	if (devpts_mnt)
-		return devpts_mnt->mnt_sb == s;
-	return 0;
-}
-
 /*
  * devpts_mount()
  *
- *     If the '-o newinstance' mount option was specified, mount a new
- *     (private) instance of devpts.  PTYs created in this instance are
- *     independent of the PTYs in other devpts instances.
- *
- *     If the '-o newinstance' option was not specified, mount/remount the
- *     initial kernel mount of devpts.  This type of mount gives the
- *     legacy, single-instance semantics.
- *
- *     The 'newinstance' option is needed to support multiple namespace
- *     semantics in devpts while preserving backward compatibility of the
- *     current 'single-namespace' semantics. i.e all mounts of devpts
- *     without the 'newinstance' mount option should bind to the initial
- *     kernel mount, like mount_single().
- *
- *     Mounts with 'newinstance' option create a new, private namespace.
- *
- *     NOTE:
- *
- *     For single-mount semantics, devpts cannot use mount_single(),
- *     because mount_single()/sget() find and use the super-block from
- *     the most recent mount of devpts. But that recent mount may be a
- *     'newinstance' mount and mount_single() would pick the newinstance
- *     super-block instead of the initial super-block.
+ *     Mount a new (private) instance of devpts.  PTYs created in this
+ *     instance are independent of the PTYs in other devpts instances.
  */
 static struct dentry *devpts_mount(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
@@ -456,18 +443,7 @@ static struct dentry *devpts_mount(struct file_system_type *fs_type,
 	if (error)
 		return ERR_PTR(error);
 
-	/* Require newinstance for all user namespace mounts to ensure
-	 * the mount options are not changed.
-	 */
-	if ((current_user_ns() != &init_user_ns) && !opts.newinstance)
-		return ERR_PTR(-EINVAL);
-
-	if (opts.newinstance)
-		s = sget(fs_type, NULL, set_anon_super, flags, NULL);
-	else
-		s = sget(fs_type, compare_init_pts_sb, set_anon_super, flags,
-			 NULL);
-
+	s = sget(fs_type, NULL, set_anon_super, flags, NULL);
 	if (IS_ERR(s))
 		return ERR_CAST(s);
 
@@ -491,18 +467,6 @@ out_undo_sget:
 	return ERR_PTR(error);
 }
 
-#else
-/*
- * This supports only the legacy single-instance semantics (no
- * multiple-instance semantics)
- */
-static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags,
-		const char *dev_name, void *data)
-{
-	return mount_single(fs_type, flags, data, devpts_fill_super);
-}
-#endif
-
 static void devpts_kill_sb(struct super_block *sb)
 {
 	struct pts_fs_info *fsi = DEVPTS_SB(sb);
@@ -516,9 +480,7 @@ static struct file_system_type devpts_fs_type = {
 	.name		= "devpts",
 	.mount		= devpts_mount,
 	.kill_sb	= devpts_kill_sb,
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
 	.fs_flags	= FS_USERNS_MOUNT | FS_USERNS_DEV_MOUNT,
-#endif
 };
 
 /*
@@ -531,16 +493,13 @@ int devpts_new_index(struct pts_fs_info *fsi)
 	int index;
 	int ida_ret;
 
-	if (!fsi)
-		return -ENODEV;
-
 retry:
 	if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
 		return -ENOMEM;
 
 	mutex_lock(&allocated_ptys_lock);
-	if (pty_count >= pty_limit -
-			(fsi->mount_opts.newinstance ? pty_reserve : 0)) {
+	if (pty_count >= (pty_limit -
+			  (fsi->mount_opts.reserve ? 0 : pty_reserve))) {
 		mutex_unlock(&allocated_ptys_lock);
 		return -ENOSPC;
 	}
@@ -571,30 +530,6 @@ void devpts_kill_index(struct pts_fs_info *fsi, int idx)
 	mutex_unlock(&allocated_ptys_lock);
 }
 
-/*
- * pty code needs to hold extra references in case of last /dev/tty close
- */
-struct pts_fs_info *devpts_get_ref(struct inode *ptmx_inode, struct file *file)
-{
-	struct super_block *sb;
-	struct pts_fs_info *fsi;
-
-	sb = pts_sb_from_inode(ptmx_inode);
-	if (!sb)
-		return NULL;
-	fsi = DEVPTS_SB(sb);
-	if (!fsi)
-		return NULL;
-
-	atomic_inc(&sb->s_active);
-	return fsi;
-}
-
-void devpts_put_ref(struct pts_fs_info *fsi)
-{
-	deactivate_super(fsi->sb);
-}
-
 /**
  * devpts_pty_new -- create a new inode in /dev/pts/
  * @ptmx_inode: inode of the master
@@ -607,16 +542,12 @@ void devpts_put_ref(struct pts_fs_info *fsi)
 struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
 {
 	struct dentry *dentry;
-	struct super_block *sb;
+	struct super_block *sb = fsi->sb;
 	struct inode *inode;
 	struct dentry *root;
 	struct pts_mount_opts *opts;
 	char s[12];
 
-	if (!fsi)
-		return ERR_PTR(-ENODEV);
-
-	sb = fsi->sb;
 	root = sb->s_root;
 	opts = &fsi->mount_opts;
 
@@ -676,20 +607,8 @@ void devpts_pty_kill(struct dentry *dentry)
 static int __init init_devpts_fs(void)
 {
 	int err = register_filesystem(&devpts_fs_type);
-	struct ctl_table_header *table;
-
 	if (!err) {
-		struct vfsmount *mnt;
-
-		table = register_sysctl_table(pty_root_table);
-		mnt = kern_mount(&devpts_fs_type);
-		if (IS_ERR(mnt)) {
-			err = PTR_ERR(mnt);
-			unregister_filesystem(&devpts_fs_type);
-			unregister_sysctl_table(table);
-		} else {
-			devpts_mnt = mnt;
-		}
+		register_sysctl_table(pty_root_table);
 	}
 	return err;
 }
diff --git a/fs/namei.c b/fs/namei.c
index 4c4f95ac8aa5..6a82fb7e2127 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1416,21 +1416,28 @@ static void follow_mount(struct path *path)
 	}
 }
 
+static int path_parent_directory(struct path *path)
+{
+	struct dentry *old = path->dentry;
+	/* rare case of legitimate dget_parent()... */
+	path->dentry = dget_parent(path->dentry);
+	dput(old);
+	if (unlikely(!path_connected(path)))
+		return -ENOENT;
+	return 0;
+}
+
 static int follow_dotdot(struct nameidata *nd)
 {
 	while(1) {
-		struct dentry *old = nd->path.dentry;
-
 		if (nd->path.dentry == nd->root.dentry &&
 		    nd->path.mnt == nd->root.mnt) {
 			break;
 		}
 		if (nd->path.dentry != nd->path.mnt->mnt_root) {
-			/* rare case of legitimate dget_parent()... */
-			nd->path.dentry = dget_parent(nd->path.dentry);
-			dput(old);
-			if (unlikely(!path_connected(&nd->path)))
-				return -ENOENT;
+			int ret = path_parent_directory(&nd->path);
+			if (ret)
+				return ret;
 			break;
 		}
 		if (!follow_up(&nd->path))
@@ -2514,6 +2521,34 @@ struct dentry *lookup_one_len_unlocked(const char *name,
 }
 EXPORT_SYMBOL(lookup_one_len_unlocked);
 
+#ifdef CONFIG_UNIX98_PTYS
+int path_pts(struct path *path)
+{
+	/* Find something mounted on "pts" in the same directory as
+	 * the input path.
+	 */
+	struct dentry *child, *parent;
+	struct qstr this;
+	int ret;
+
+	ret = path_parent_directory(path);
+	if (ret)
+		return ret;
+
+	parent = path->dentry;
+	this.name = "pts";
+	this.len = 3;
+	child = d_hash_and_lookup(parent, &this);
+	if (!child)
+		return -ENOENT;
+
+	path->dentry = child;
+	dput(parent);
+	follow_mount(path);
+	return 0;
+}
+#endif
+
 int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
 		 struct path *path, int *empty)
 {
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
index 5871f292b596..277ab9af9ac2 100644
--- a/include/linux/devpts_fs.h
+++ b/include/linux/devpts_fs.h
@@ -15,13 +15,12 @@
 
 #include <linux/errno.h>
 
-struct pts_fs_info;
-
 #ifdef CONFIG_UNIX98_PTYS
 
-/* Look up a pts fs info and get a ref to it */
-struct pts_fs_info *devpts_get_ref(struct inode *, struct file *);
-void devpts_put_ref(struct pts_fs_info *);
+struct pts_fs_info;
+
+struct pts_fs_info *devpts_acquire(struct file *);
+void devpts_release(struct pts_fs_info *);
 
 int devpts_new_index(struct pts_fs_info *);
 void devpts_kill_index(struct pts_fs_info *, int);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index ec5ec2818a28..d3d0398f2a1b 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -45,6 +45,8 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 #define LOOKUP_ROOT		0x2000
 #define LOOKUP_EMPTY		0x4000
 
+extern int path_pts(struct path *path);
+
 extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
 
 static inline int user_path_at(int dfd, const char __user *name, unsigned flags,
-- 
2.8.3

  reply	other threads:[~2016-06-02 15:43 UTC|newest]

Thread overview: 154+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <43AD2BA7-B594-4299-95F3-D86FD38AF21B@zytor.com>
     [not found] ` <87egexpf4o.fsf@x220.int.ebiederm.org>
     [not found]   ` <CA+55aFw9Bg+Zh_T4zP487n3ieaxoMHgZ_nNJVdpSR4kQK9gQ9w@mail.gmail.com>
     [not found]     ` <1CB621EF-1647-463B-A144-D611DB150E15@zytor.com>
     [not found]       ` <20151208223135.GA8352@kroah.com>
     [not found]         ` <87oae0h2bo.fsf@x220.int.ebiederm.org>
     [not found]           ` <56677DE3.5040705@zytor.com>
     [not found]             ` <20151209012311.GA11794@kroah.com>
     [not found]               ` <84B136DF-55E4-476A-9CB2-062B15677EE5@zytor.com>
     [not found]                 ` <20151209013859.GA12442@kroah.com>
     [not found]                   ` <20151209083225.GA30452@1wt.eu>
2015-12-11 19:40                     ` [PATCH] devpts: Sensible /dev/ptmx & force newinstance Eric W. Biederman
2015-12-11 20:50                       ` Linus Torvalds
2015-12-11 21:03                         ` Eric W. Biederman
2015-12-11 21:04                       ` Al Viro
2015-12-11 21:11                         ` Eric W. Biederman
2015-12-11 21:48                           ` Andy Lutomirski
2015-12-11 22:07                             ` H. Peter Anvin
2015-12-11 22:12                               ` Andy Lutomirski
2015-12-11 22:18                                 ` H. Peter Anvin
2015-12-11 22:24                                   ` Andy Lutomirski
2015-12-11 22:29                                     ` H. Peter Anvin
2015-12-11 22:35                                 ` Eric W. Biederman
2015-12-11 22:52                                   ` Andy Lutomirski
2015-12-11 22:58                                     ` Jann Horn
2015-12-11 23:00                                       ` Andy Lutomirski
2015-12-11 23:07                                         ` H. Peter Anvin
2015-12-11 23:16                                           ` Andy Lutomirski
2015-12-11 23:30                                             ` H. Peter Anvin
2015-12-11 22:57                                   ` H. Peter Anvin
2015-12-14 19:47                       ` Peter Hurley
2015-12-14 19:55                         ` H. Peter Anvin
2015-12-19 21:13                         ` Eric W. Biederman
2015-12-20  4:11                           ` Eric W. Biederman
2015-12-20  4:35                             ` H. Peter Anvin
2015-12-20  9:42                               ` Eric W. Biederman
2015-12-21 22:03                                 ` Eric W. Biederman
2015-12-21 22:23                                   ` Linus Torvalds
2016-04-05  0:03                                     ` [PATCH 00/13] devpts: New instances for every mount Eric W. Biederman
2016-04-05  1:29                                       ` [PATCH 01/13] devpts: Teach /dev/ptmx to find the associated devpts via path lookup Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 02/13] devpts: More obvious check for the system devpts in pty allocation Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 03/13] devpts: Cleanup newinstance parsing Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 04/13] devpts: Stop rolling devpts_remount by hand in devpts_mount Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 05/13] devpts: Fail early (if appropriate) on overmount Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 06/13] devpts: Use the same default mode for both /dev/ptmx and dev/pts/ptmx Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 07/13] devpts: Move parse_mount_options into fill_super Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 08/13] devpts: Make devpts_kill_sb safe if fsi is NULL Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 09/13] devpts: Move the creation of /dev/pts/ptmx into fill_super Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 10/13] devpts: Simplify devpts_mount by using mount_nodev Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 11/13] vfs: Implement mount_super_once Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 12/13] devpts: Always return a distinct instance when mounting Eric W. Biederman
2016-04-05  1:29                                         ` [PATCH 13/13] devpts: Kill the DEVPTS_MULTIPLE_INSTANCE config option Eric W. Biederman
2016-04-05  2:54                                         ` [PATCH 01/13] devpts: Teach /dev/ptmx to find the associated devpts via path lookup Al Viro
2016-04-05  3:03                                           ` Al Viro
2016-04-08 18:54                                             ` Eric W. Biederman
2016-04-07 16:06                                         ` Linus Torvalds
2016-04-08 18:51                                           ` Eric W. Biederman
2016-04-08 19:05                                             ` Linus Torvalds
2016-04-08 20:05                                               ` Eric W. Biederman
2016-04-08 20:43                                               ` Andy Lutomirski
2016-04-08 21:29                                                 ` Eric W. Biederman
2016-04-08 21:54                                                   ` Linus Torvalds
2016-04-08 23:03                                                     ` Eric W. Biederman
2016-04-08 21:56                                                   ` Andy Lutomirski
2016-04-09 13:09                                             ` One Thousand Gnomes
2016-04-09 14:10                                               ` H. Peter Anvin
2016-04-09 14:45                                                 ` Eric W. Biederman
2016-04-09 22:37                                                   ` H. Peter Anvin
2016-04-10  0:01                                                     ` Linus Torvalds
2016-04-10  0:06                                                       ` H. Peter Anvin
2016-04-10  0:16                                                         ` Linus Torvalds
2016-04-10  0:44                                                           ` Andy Lutomirski
     [not found]                                                             ` <CA+55aFzs00iDkYhvFCq=AZMVcNL0+oZT4SeimTeVurJq=5ZS3A@mail.gmail.com>
2016-04-11 14:48                                                               ` H. Peter Anvin
2016-04-12  1:31                                                                 ` Al Viro
2016-04-11 20:12                                                               ` Andy Lutomirski
2016-04-11 20:10                                                                 ` Eric W. Biederman
2016-04-11 20:16                                                                 ` H. Peter Anvin
2016-04-11 23:37                                                                   ` Eric W. Biederman
2016-04-12  0:01                                                                     ` Linus Torvalds
2016-04-12  0:10                                                                       ` Eric W. Biederman
2016-04-12  1:06                                                                         ` H. Peter Anvin
2016-04-12  1:18                                                                           ` Linus Torvalds
2016-04-12  1:23                                                                           ` Eric W. Biederman
2016-04-12  1:47                                                                             ` Al Viro
2016-04-12  1:34                                                                         ` Al Viro
2016-04-12  2:16                                                                           ` Eric W. Biederman
2016-04-12 17:44                                                                 ` Andy Lutomirski
2016-04-12 18:12                                                                   ` Linus Torvalds
2016-04-12 19:07                                                                     ` H. Peter Anvin
2016-04-15 15:34                                                                       ` [PATCH 01/16] devpts: Attempting to get it right Eric W. Biederman
2016-04-15 15:35                                                                         ` [PATCH 01/16] devpts: Use the same default mode for both /dev/ptmx and dev/pts/ptmx Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 02/16] devpts: Set the proper fops for /dev/pts/ptmx Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 03/16] vfs: Implement vfs_loopback_mount Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 04/16] devpts: Teach /dev/ptmx to automount the appropriate devpts via path lookup Eric W. Biederman
2016-04-15 22:03                                                                             ` Jann Horn
2016-04-19 18:46                                                                               ` Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 05/16] vfs: Allow unlink, and rename on expirable file mounts Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 06/16] devpts: More obvious check for the system devpts in pty allocation Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 07/16] devpts: Cleanup newinstance parsing Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 08/16] devpts: Stop rolling devpts_remount by hand in devpts_mount Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 09/16] devpts: Fail early (if appropriate) on overmount Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 10/16] devpts: Move parse_mount_options into fill_super Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 11/16] devpts: Make devpts_kill_sb safe if fsi is NULL Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 12/16] devpts: Move the creation of /dev/pts/ptmx into fill_super Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 13/16] devpts: Simplify devpts_mount by using mount_nodev Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 14/16] vfs: Implement mount_super_once Eric W. Biederman
2016-04-15 23:02                                                                             ` Linus Torvalds
2016-04-19 18:22                                                                               ` Eric W. Biederman
2016-04-19 18:47                                                                                 ` H. Peter Anvin
2016-04-19 19:03                                                                                   ` Eric W. Biederman
2016-04-19 19:25                                                                                     ` H. Peter Anvin
2016-04-19 19:26                                                                                       ` H. Peter Anvin
2016-04-20  3:27                                                                                         ` Eric W. Biederman
2016-04-20 11:50                                                                                           ` Austin S. Hemmelgarn
2016-04-20 16:12                                                                                             ` H. Peter Anvin
2016-04-19 18:55                                                                                 ` H. Peter Anvin
2016-04-19 23:29                                                                                 ` Linus Torvalds
2016-04-20  1:24                                                                                   ` Linus Torvalds
2016-04-20  1:37                                                                                     ` H. Peter Anvin
2016-04-15 15:35                                                                           ` [PATCH 15/16] devpts: Always return a distinct instance when mounting Eric W. Biederman
2016-04-15 15:35                                                                           ` [PATCH 16/16] devpts: Kill the DEVPTS_MULTIPLE_INSTANCE config option Eric W. Biederman
2016-04-15 16:49                                                                         ` [PATCH 01/16] devpts: Attempting to get it right Andy Lutomirski
2016-04-15 20:43                                                                           ` Eric W. Biederman
2016-04-15 21:29                                                                             ` H. Peter Anvin
2016-04-19 19:00                                                                               ` Eric W. Biederman
2016-04-16 18:31                                                                         ` Linus Torvalds
2016-04-19 18:44                                                                           ` Does anyone care about a race free ptsname? Eric W. Biederman
2016-04-19 19:16                                                                             ` H. Peter Anvin
2016-04-19 20:32                                                                               ` Eric W. Biederman
2016-04-19 20:55                                                                                 ` H. Peter Anvin
2016-04-19 20:42                                                                             ` Serge E. Hallyn
2016-04-19 23:23                                                                             ` Linus Torvalds
2016-04-19 23:39                                                                               ` H. Peter Anvin
2016-04-20  0:18                                                                                 ` Linus Torvalds
2016-04-20  1:48                                                                                 ` Serge E. Hallyn
2016-04-19 22:06                                                                           ` [PATCH 01/16] devpts: Attempting to get it right Eric W. Biederman
2016-04-19 23:35                                                                             ` Linus Torvalds
2016-04-20  0:24                                                                               ` Peter Hurley
2016-04-20  0:49                                                                                 ` Peter Hurley
2016-04-20  3:04                                                                               ` [PATCH] devpts: Make each mount of devpts an independent filesystem Eric W. Biederman
2016-04-20  3:25                                                                                 ` Al Viro
2016-04-20  3:43                                                                                   ` Eric W. Biederman
2016-04-20  4:11                                                                                     ` Al Viro
2016-04-20  4:21                                                                                       ` Eric W. Biederman
2016-04-20  4:36                                                                                 ` Konstantin Khlebnikov
2016-04-20  4:49                                                                                   ` Linus Torvalds
2016-04-20 14:55                                                                                     ` Eric W. Biederman
2016-04-20 15:34                                                                                       ` Konstantin Khlebnikov
2016-04-20 15:50                                                                                         ` Eric W. Biederman
2016-04-20 17:00                                                                                         ` [PATCH v2] " Eric W. Biederman
     [not found]                                                                                           ` <874mabt3df.fsf_-_@x220.int.ebiederm.org>
2016-05-06 19:04                                                                                             ` [PATCH 1/1] " Eric W. Biederman
2016-05-06 19:35                                                                                             ` [PATCH 0/1] devpts: Removing the need for pt_chown Greg KH
2016-05-06 19:45                                                                                               ` Peter Hurley
2016-05-06 19:54                                                                                                 ` Greg KH
2016-06-02 15:29                                                                                                   ` Eric W. Biederman [this message]
2016-06-02 18:57                                                                                                     ` [PATCH tty-next] devpts: Make each mount of devpts an independent filesystem Linus Torvalds
2016-06-02 20:22                                                                                                       ` Eric W. Biederman
2016-06-02 20:36                                                                                                         ` H. Peter Anvin
2016-06-02 21:23                                                                                                           ` Eric W. Biederman
2016-06-02 21:44                                                                                                             ` Linus Torvalds
2016-04-11 23:49                                                               ` [PATCH 01/13] devpts: Teach /dev/ptmx to find the associated devpts via path lookup Eric W. Biederman
2016-04-12  0:08                                                                 ` Linus Torvalds
2016-04-12  0:22                                                                   ` Eric W. Biederman
2016-04-12  0:50                                                                     ` Linus Torvalds
2016-04-11 20:05                                                       ` Eric W. Biederman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=878tyn4nis.fsf_-_@x220.int.ebiederm.org \
    --to=ebiederm@xmission.com \
    --cc=aurelien@aurel32.net \
    --cc=fw@deneb.enyo.de \
    --cc=gnomes@lxorguk.ukuu.org.uk \
    --cc=greg@kroah.com \
    --cc=hpa@zytor.com \
    --cc=jann@thejh.net \
    --cc=jslaby@suse.com \
    --cc=koct9i@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=peter@hurleysoftware.com \
    --cc=security@debian.org \
    --cc=security@kernel.org \
    --cc=security@ubuntu.com \
    --cc=serge.hallyn@ubuntu.com \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    --cc=w@1wt.eu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).