2005-04-17 02:20:36 +04:00
|
|
|
/* -*- linux-c -*- --------------------------------------------------------- *
|
|
|
|
*
|
|
|
|
* linux/fs/devpts/inode.c
|
|
|
|
*
|
|
|
|
* Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
|
|
|
|
*
|
|
|
|
* This file is part of the Linux kernel and is made available under
|
|
|
|
* the terms of the GNU General Public License, version 2, or at your
|
|
|
|
* option, any later version, incorporated herein by reference.
|
|
|
|
*
|
|
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
|
2014-06-07 01:37:34 +04:00
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/namei.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 11:04:11 +03:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
#include <linux/mount.h>
|
|
|
|
#include <linux/tty.h>
|
2008-04-30 11:54:21 +04:00
|
|
|
#include <linux/mutex.h>
|
2009-09-23 03:43:33 +04:00
|
|
|
#include <linux/magic.h>
|
2008-04-30 11:54:21 +04:00
|
|
|
#include <linux/idr.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
#include <linux/devpts_fs.h>
|
2006-03-23 14:00:59 +03:00
|
|
|
#include <linux/parser.h>
|
2007-05-08 11:24:18 +04:00
|
|
|
#include <linux/fsnotify.h>
|
2008-02-08 15:21:41 +03:00
|
|
|
#include <linux/seq_file.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-02-08 15:21:41 +03:00
|
|
|
#define DEVPTS_DEFAULT_MODE 0600
|
2009-01-02 16:42:02 +03:00
|
|
|
/*
|
|
|
|
* ptmx is a new node in /dev/pts and will be unused in legacy (single-
|
|
|
|
* instance) mode. To prevent surprises in user space, set permissions of
|
|
|
|
* ptmx to 0. Use 'chmod' or remount with '-o ptmxmode' to set meaningful
|
|
|
|
* permissions.
|
|
|
|
*/
|
|
|
|
#define DEVPTS_DEFAULT_PTMX_MODE 0000
|
2008-10-13 13:43:08 +04:00
|
|
|
#define PTMX_MINOR 2
|
2008-02-08 15:21:41 +03:00
|
|
|
|
2012-01-05 13:06:02 +04:00
|
|
|
/*
|
|
|
|
* sysctl support for setting limits on the number of Unix98 ptys allocated.
|
|
|
|
* Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
|
|
|
|
*/
|
|
|
|
static int pty_limit = NR_UNIX98_PTY_DEFAULT;
|
2012-01-05 13:06:11 +04:00
|
|
|
static int pty_reserve = NR_UNIX98_PTY_RESERVE;
|
2012-01-05 13:06:02 +04:00
|
|
|
static int pty_limit_min;
|
2012-01-05 13:06:11 +04:00
|
|
|
static int pty_limit_max = INT_MAX;
|
2012-01-05 13:06:02 +04:00
|
|
|
static int pty_count;
|
|
|
|
|
|
|
|
static struct ctl_table pty_table[] = {
|
|
|
|
{
|
|
|
|
.procname = "max",
|
|
|
|
.maxlen = sizeof(int),
|
|
|
|
.mode = 0644,
|
|
|
|
.data = &pty_limit,
|
|
|
|
.proc_handler = proc_dointvec_minmax,
|
|
|
|
.extra1 = &pty_limit_min,
|
|
|
|
.extra2 = &pty_limit_max,
|
2012-01-05 13:06:11 +04:00
|
|
|
}, {
|
|
|
|
.procname = "reserve",
|
|
|
|
.maxlen = sizeof(int),
|
|
|
|
.mode = 0644,
|
|
|
|
.data = &pty_reserve,
|
|
|
|
.proc_handler = proc_dointvec_minmax,
|
|
|
|
.extra1 = &pty_limit_min,
|
|
|
|
.extra2 = &pty_limit_max,
|
2012-01-05 13:06:02 +04:00
|
|
|
}, {
|
|
|
|
.procname = "nr",
|
|
|
|
.maxlen = sizeof(int),
|
|
|
|
.mode = 0444,
|
|
|
|
.data = &pty_count,
|
|
|
|
.proc_handler = proc_dointvec,
|
|
|
|
},
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct ctl_table pty_kern_table[] = {
|
|
|
|
{
|
|
|
|
.procname = "pty",
|
|
|
|
.mode = 0555,
|
|
|
|
.child = pty_table,
|
|
|
|
},
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct ctl_table pty_root_table[] = {
|
|
|
|
{
|
|
|
|
.procname = "kernel",
|
|
|
|
.mode = 0555,
|
|
|
|
.child = pty_kern_table,
|
|
|
|
},
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2008-04-30 11:54:21 +04:00
|
|
|
static DEFINE_MUTEX(allocated_ptys_lock);
|
|
|
|
|
2009-01-02 16:41:33 +03:00
|
|
|
struct pts_mount_opts {
|
2005-04-17 02:20:36 +04:00
|
|
|
int setuid;
|
|
|
|
int setgid;
|
2012-02-08 04:22:56 +04:00
|
|
|
kuid_t uid;
|
|
|
|
kgid_t gid;
|
2005-04-17 02:20:36 +04:00
|
|
|
umode_t mode;
|
2009-01-02 16:42:02 +03:00
|
|
|
umode_t ptmxmode;
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
int reserve;
|
2012-01-05 13:06:11 +04:00
|
|
|
int max;
|
2009-01-02 16:41:33 +03:00
|
|
|
};
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2006-03-23 14:00:59 +03:00
|
|
|
enum {
|
2012-01-05 13:06:11 +04:00
|
|
|
Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_max,
|
2006-03-23 14:00:59 +03:00
|
|
|
Opt_err
|
|
|
|
};
|
|
|
|
|
2008-10-13 13:46:57 +04:00
|
|
|
static const match_table_t tokens = {
|
2006-03-23 14:00:59 +03:00
|
|
|
{Opt_uid, "uid=%u"},
|
|
|
|
{Opt_gid, "gid=%u"},
|
|
|
|
{Opt_mode, "mode=%o"},
|
2009-01-02 16:42:02 +03:00
|
|
|
{Opt_ptmxmode, "ptmxmode=%o"},
|
Enable multiple instances of devpts
To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.
But to preserve backward compatibility, enable this support for multiple
instances only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
- '-o newinstance' mount option is specified while mounting devpts
To use multi-instance mount, a container startup script could:
$ ns_exec -cm /bin/bash
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ mount -o bind /dev/pts/ptmx /dev/ptmx
$ /usr/sbin/sshd -p 1234
where 'ns_exec -cm /bin/bash' is 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.
USER-SPACE-IMPACT:
- See Documentation/fs/devpts.txt (included in next patch) for user-
space impact in multi-instance and mixed-mode operation.
TODO:
- Update mount(8), pts(4) man pages. Highlight impact of not
redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.
Changelog[v6]:
- [Dave Hansen] Use new get_init_pts_sb() interface
- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
- [Serge Hallyn] Check error return from get_sb_single() (now
get_init_pts_sb())
- devpts_pty_kill(): don't dput error dentries
Changelog[v5]:
- Move get_sb_ref() definition to earlier patch
- Move usage info to Documentation/filesystems/devpts.txt (next patch)
- Make ptmx node even in init_pts_ns, now that default mode is 0000
(defined in earlier patch, enabled here).
- Cache ptmx dentry and use to update mode during remount
(defined in earlier patch, enabled here).
- Bugfix: explicitly ignore newinstance on remount (if newinstance was
specified on remount of initial mount, it would be ignored but
/proc/mounts would imply that the option was set)
Changelog[v4]:
- Update patch description to address H. Peter Anvin's comments
- Consolidate multi-instance mode code under new config token,
CONFIG_DEVPTS_MULTIPLE_INSTANCE.
- Move usage-details from patch description to
Documentation/fs/devpts.txt
Changelog[v3]:
- Rename new mount option to 'newinstance'
- Create ptmx nodes only in 'newinstance' mounts
- Bugfix: parse_mount_options() modifies @data but since we need to
parse the @data twice (once in devpts_get_sb() and once during
do_remount_sb()), parse a local copy of @data in devpts_get_sb().
(restructured code in devpts_get_sb() to fix this)
Changelog[v2]:
- Support both single-mount and multiple-mount semantics and
provide '-onewmnt' option to select the semantics.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-01-02 16:42:27 +03:00
|
|
|
{Opt_newinstance, "newinstance"},
|
2012-01-05 13:06:11 +04:00
|
|
|
{Opt_max, "max=%d"},
|
2006-03-23 14:00:59 +03:00
|
|
|
{Opt_err, NULL}
|
|
|
|
};
|
|
|
|
|
2009-01-02 16:41:21 +03:00
|
|
|
struct pts_fs_info {
|
|
|
|
struct ida allocated_ptys;
|
2009-01-02 16:41:33 +03:00
|
|
|
struct pts_mount_opts mount_opts;
|
devpts: clean up interface to pty drivers
This gets rid of the horrible notion of having that
struct inode *ptmx_inode
be the linchpin of the interface between the pty code and devpts.
By de-emphasizing the ptmx inode, a lot of things actually get cleaner,
and we will have a much saner way forward. In particular, this will
allow us to associate with any particular devpts instance at open-time,
and not be artificially tied to one particular ptmx inode.
The patch itself is actually fairly straightforward, and apart from some
locking and return path cleanups it's pretty mechanical:
- the interfaces that devpts exposes all take "struct pts_fs_info *"
instead of "struct inode *ptmx_inode" now.
NOTE! The "struct pts_fs_info" thing is a completely opaque structure
as far as the pty driver is concerned: it's still declared entirely
internally to devpts. So the pty code can't actually access it in any
way, just pass it as a "cookie" to the devpts code.
- the "look up the pts fs info" is now a single clear operation, that
also does the reference count increment on the pts superblock.
So "devpts_add/del_ref()" is gone, and replaced by a "lookup and get
ref" operation (devpts_get_ref(inode)), along with a "put ref" op
(devpts_put_ref()).
- the pty master "tty->driver_data" field now contains the pts_fs_info,
not the ptmx inode.
- because we don't care about the ptmx inode any more as some kind of
base index, the ref counting can now drop the inode games - it just
gets the ref on the superblock.
- the pts_fs_info now has a back-pointer to the super_block. That's so
that we can easily look up the information we actually need. Although
quite often, the pts fs info was actually all we wanted, and not having
to look it up based on some magical inode makes things more
straightforward.
In particular, now that "devpts_get_ref(inode)" operation should really
be the *only* place we need to look up what devpts instance we're
associated with, and we do it exactly once, at ptmx_open() time.
The other side of this is that one ptmx node could now be associated
with multiple different devpts instances - you could have a single
/dev/ptmx node, and then have multiple mount namespaces with their own
instances of devpts mounted on /dev/pts/. And that's all perfectly sane
in a model where we just look up the pts instance at open time.
This will eventually allow us to get rid of our odd single-vs-multiple
pts instance model, but this patch in itself changes no semantics, only
an internal binding model.
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Greg KH <greg@kroah.com>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-17 01:16:07 +03:00
|
|
|
struct super_block *sb;
|
2009-01-02 16:42:02 +03:00
|
|
|
struct dentry *ptmx_dentry;
|
2009-01-02 16:41:21 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
|
|
|
|
{
|
|
|
|
return sb->s_fs_info;
|
|
|
|
}
|
|
|
|
|
pty: fix the cached path of the pty slave file descriptor in the master
Christian Brauner reported that if you use the TIOCGPTPEER ioctl() to
get a slave pty file descriptor, the resulting file descriptor doesn't
look right in /proc/<pid>/fd/<fd>. In particular, he wanted to use
readlink() on /proc/self/fd/<fd> to get the pathname of the slave pty
(basically implementing "ptsname{_r}()").
The reason for that was that we had generated the wrong 'struct path'
when we create the pty in ptmx_open().
In particular, the dentry was correct, but the vfsmount pointed to the
mount of the ptmx node. That _can_ be correct - in case you use
"/dev/pts/ptmx" to open the master - but usually is not. The normal
case is to use /dev/ptmx, which then looks up the pts/ directory, and
then the vfsmount of the ptmx node is obviously the /dev directory, not
the /dev/pts/ directory.
We actually did have the right vfsmount available, but in the wrong
place (it gets looked up in 'devpts_acquire()' when we get a reference
to the pts filesystem), and so ptmx_open() used the wrong mnt pointer.
The end result of this confusion was that the pty worked fine, but when
if you did TIOCGPTPEER to get the slave side of the pty, end end result
would also work, but have that dodgy 'struct path'.
And then when doing "d_path()" on to get the pathname, the vfsmount
would not match the root of the pts directory, and d_path() would return
an empty pathname thinking that the entry had escaped a bind mount into
another mount.
This fixes the problem by making devpts_acquire() return the vfsmount
for the pts filesystem, allowing ptmx_open() to trivially just use the
right mount for the pts dentry, and create the proper 'struct path'.
Reported-by: Christian Brauner <christian.brauner@ubuntu.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Eric Biederman <ebiederm@xmission.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-08-17 03:08:07 +03:00
|
|
|
struct pts_fs_info *devpts_acquire(struct file *filp, struct vfsmount **ptsmnt)
|
2009-01-02 16:41:11 +03:00
|
|
|
{
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
struct pts_fs_info *result;
|
|
|
|
struct path path;
|
|
|
|
struct super_block *sb;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
path = filp->f_path;
|
|
|
|
path_get(&path);
|
pty: fix the cached path of the pty slave file descriptor in the master
Christian Brauner reported that if you use the TIOCGPTPEER ioctl() to
get a slave pty file descriptor, the resulting file descriptor doesn't
look right in /proc/<pid>/fd/<fd>. In particular, he wanted to use
readlink() on /proc/self/fd/<fd> to get the pathname of the slave pty
(basically implementing "ptsname{_r}()").
The reason for that was that we had generated the wrong 'struct path'
when we create the pty in ptmx_open().
In particular, the dentry was correct, but the vfsmount pointed to the
mount of the ptmx node. That _can_ be correct - in case you use
"/dev/pts/ptmx" to open the master - but usually is not. The normal
case is to use /dev/ptmx, which then looks up the pts/ directory, and
then the vfsmount of the ptmx node is obviously the /dev directory, not
the /dev/pts/ directory.
We actually did have the right vfsmount available, but in the wrong
place (it gets looked up in 'devpts_acquire()' when we get a reference
to the pts filesystem), and so ptmx_open() used the wrong mnt pointer.
The end result of this confusion was that the pty worked fine, but when
if you did TIOCGPTPEER to get the slave side of the pty, end end result
would also work, but have that dodgy 'struct path'.
And then when doing "d_path()" on to get the pathname, the vfsmount
would not match the root of the pts directory, and d_path() would return
an empty pathname thinking that the entry had escaped a bind mount into
another mount.
This fixes the problem by making devpts_acquire() return the vfsmount
for the pts filesystem, allowing ptmx_open() to trivially just use the
right mount for the pts dentry, and create the proper 'struct path'.
Reported-by: Christian Brauner <christian.brauner@ubuntu.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Eric Biederman <ebiederm@xmission.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-08-17 03:08:07 +03:00
|
|
|
*ptsmnt = NULL;
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
|
|
|
|
/* 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);
|
pty: fix the cached path of the pty slave file descriptor in the master
Christian Brauner reported that if you use the TIOCGPTPEER ioctl() to
get a slave pty file descriptor, the resulting file descriptor doesn't
look right in /proc/<pid>/fd/<fd>. In particular, he wanted to use
readlink() on /proc/self/fd/<fd> to get the pathname of the slave pty
(basically implementing "ptsname{_r}()").
The reason for that was that we had generated the wrong 'struct path'
when we create the pty in ptmx_open().
In particular, the dentry was correct, but the vfsmount pointed to the
mount of the ptmx node. That _can_ be correct - in case you use
"/dev/pts/ptmx" to open the master - but usually is not. The normal
case is to use /dev/ptmx, which then looks up the pts/ directory, and
then the vfsmount of the ptmx node is obviously the /dev directory, not
the /dev/pts/ directory.
We actually did have the right vfsmount available, but in the wrong
place (it gets looked up in 'devpts_acquire()' when we get a reference
to the pts filesystem), and so ptmx_open() used the wrong mnt pointer.
The end result of this confusion was that the pty worked fine, but when
if you did TIOCGPTPEER to get the slave side of the pty, end end result
would also work, but have that dodgy 'struct path'.
And then when doing "d_path()" on to get the pathname, the vfsmount
would not match the root of the pts directory, and d_path() would return
an empty pathname thinking that the entry had escaped a bind mount into
another mount.
This fixes the problem by making devpts_acquire() return the vfsmount
for the pts filesystem, allowing ptmx_open() to trivially just use the
right mount for the pts dentry, and create the proper 'struct path'.
Reported-by: Christian Brauner <christian.brauner@ubuntu.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Eric Biederman <ebiederm@xmission.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-08-17 03:08:07 +03:00
|
|
|
*ptsmnt = mntget(path.mnt);
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
result = DEVPTS_SB(sb);
|
|
|
|
|
|
|
|
out:
|
|
|
|
path_put(&path);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void devpts_release(struct pts_fs_info *fsi)
|
|
|
|
{
|
|
|
|
deactivate_super(fsi->sb);
|
2009-01-02 16:41:11 +03:00
|
|
|
}
|
|
|
|
|
Enable multiple instances of devpts
To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.
But to preserve backward compatibility, enable this support for multiple
instances only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
- '-o newinstance' mount option is specified while mounting devpts
To use multi-instance mount, a container startup script could:
$ ns_exec -cm /bin/bash
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ mount -o bind /dev/pts/ptmx /dev/ptmx
$ /usr/sbin/sshd -p 1234
where 'ns_exec -cm /bin/bash' is 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.
USER-SPACE-IMPACT:
- See Documentation/fs/devpts.txt (included in next patch) for user-
space impact in multi-instance and mixed-mode operation.
TODO:
- Update mount(8), pts(4) man pages. Highlight impact of not
redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.
Changelog[v6]:
- [Dave Hansen] Use new get_init_pts_sb() interface
- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
- [Serge Hallyn] Check error return from get_sb_single() (now
get_init_pts_sb())
- devpts_pty_kill(): don't dput error dentries
Changelog[v5]:
- Move get_sb_ref() definition to earlier patch
- Move usage info to Documentation/filesystems/devpts.txt (next patch)
- Make ptmx node even in init_pts_ns, now that default mode is 0000
(defined in earlier patch, enabled here).
- Cache ptmx dentry and use to update mode during remount
(defined in earlier patch, enabled here).
- Bugfix: explicitly ignore newinstance on remount (if newinstance was
specified on remount of initial mount, it would be ignored but
/proc/mounts would imply that the option was set)
Changelog[v4]:
- Update patch description to address H. Peter Anvin's comments
- Consolidate multi-instance mode code under new config token,
CONFIG_DEVPTS_MULTIPLE_INSTANCE.
- Move usage-details from patch description to
Documentation/fs/devpts.txt
Changelog[v3]:
- Rename new mount option to 'newinstance'
- Create ptmx nodes only in 'newinstance' mounts
- Bugfix: parse_mount_options() modifies @data but since we need to
parse the @data twice (once in devpts_get_sb() and once during
do_remount_sb()), parse a local copy of @data in devpts_get_sb().
(restructured code in devpts_get_sb() to fix this)
Changelog[v2]:
- Support both single-mount and multiple-mount semantics and
provide '-onewmnt' option to select the semantics.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-01-02 16:42:27 +03:00
|
|
|
#define PARSE_MOUNT 0
|
|
|
|
#define PARSE_REMOUNT 1
|
|
|
|
|
2009-05-15 06:38:24 +04:00
|
|
|
/*
|
|
|
|
* parse_mount_options():
|
2014-06-07 01:37:34 +04:00
|
|
|
* Set @opts to mount options specified in @data. If an option is not
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
* specified in @data, set it to its default value.
|
2009-05-15 06:38:24 +04:00
|
|
|
*
|
|
|
|
* Note: @data may be NULL (in which case all options are set to default).
|
|
|
|
*/
|
Enable multiple instances of devpts
To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.
But to preserve backward compatibility, enable this support for multiple
instances only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
- '-o newinstance' mount option is specified while mounting devpts
To use multi-instance mount, a container startup script could:
$ ns_exec -cm /bin/bash
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ mount -o bind /dev/pts/ptmx /dev/ptmx
$ /usr/sbin/sshd -p 1234
where 'ns_exec -cm /bin/bash' is 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.
USER-SPACE-IMPACT:
- See Documentation/fs/devpts.txt (included in next patch) for user-
space impact in multi-instance and mixed-mode operation.
TODO:
- Update mount(8), pts(4) man pages. Highlight impact of not
redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.
Changelog[v6]:
- [Dave Hansen] Use new get_init_pts_sb() interface
- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
- [Serge Hallyn] Check error return from get_sb_single() (now
get_init_pts_sb())
- devpts_pty_kill(): don't dput error dentries
Changelog[v5]:
- Move get_sb_ref() definition to earlier patch
- Move usage info to Documentation/filesystems/devpts.txt (next patch)
- Make ptmx node even in init_pts_ns, now that default mode is 0000
(defined in earlier patch, enabled here).
- Cache ptmx dentry and use to update mode during remount
(defined in earlier patch, enabled here).
- Bugfix: explicitly ignore newinstance on remount (if newinstance was
specified on remount of initial mount, it would be ignored but
/proc/mounts would imply that the option was set)
Changelog[v4]:
- Update patch description to address H. Peter Anvin's comments
- Consolidate multi-instance mode code under new config token,
CONFIG_DEVPTS_MULTIPLE_INSTANCE.
- Move usage-details from patch description to
Documentation/fs/devpts.txt
Changelog[v3]:
- Rename new mount option to 'newinstance'
- Create ptmx nodes only in 'newinstance' mounts
- Bugfix: parse_mount_options() modifies @data but since we need to
parse the @data twice (once in devpts_get_sb() and once during
do_remount_sb()), parse a local copy of @data in devpts_get_sb().
(restructured code in devpts_get_sb() to fix this)
Changelog[v2]:
- Support both single-mount and multiple-mount semantics and
provide '-onewmnt' option to select the semantics.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-01-02 16:42:27 +03:00
|
|
|
static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2006-03-23 14:00:59 +03:00
|
|
|
char *p;
|
2012-02-08 04:22:56 +04:00
|
|
|
kuid_t uid;
|
|
|
|
kgid_t gid;
|
2006-03-23 14:00:59 +03:00
|
|
|
|
2009-01-02 16:41:33 +03:00
|
|
|
opts->setuid = 0;
|
|
|
|
opts->setgid = 0;
|
2012-02-08 04:22:56 +04:00
|
|
|
opts->uid = GLOBAL_ROOT_UID;
|
|
|
|
opts->gid = GLOBAL_ROOT_GID;
|
2009-01-02 16:41:33 +03:00
|
|
|
opts->mode = DEVPTS_DEFAULT_MODE;
|
2009-01-02 16:42:02 +03:00
|
|
|
opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
|
2012-01-05 13:06:11 +04:00
|
|
|
opts->max = NR_UNIX98_PTY_MAX;
|
2006-03-23 14:00:59 +03:00
|
|
|
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
/* Only allow instances mounted from the initial mount
|
|
|
|
* namespace to tap the reserve pool of ptys.
|
|
|
|
*/
|
Enable multiple instances of devpts
To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.
But to preserve backward compatibility, enable this support for multiple
instances only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
- '-o newinstance' mount option is specified while mounting devpts
To use multi-instance mount, a container startup script could:
$ ns_exec -cm /bin/bash
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ mount -o bind /dev/pts/ptmx /dev/ptmx
$ /usr/sbin/sshd -p 1234
where 'ns_exec -cm /bin/bash' is 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.
USER-SPACE-IMPACT:
- See Documentation/fs/devpts.txt (included in next patch) for user-
space impact in multi-instance and mixed-mode operation.
TODO:
- Update mount(8), pts(4) man pages. Highlight impact of not
redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.
Changelog[v6]:
- [Dave Hansen] Use new get_init_pts_sb() interface
- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
- [Serge Hallyn] Check error return from get_sb_single() (now
get_init_pts_sb())
- devpts_pty_kill(): don't dput error dentries
Changelog[v5]:
- Move get_sb_ref() definition to earlier patch
- Move usage info to Documentation/filesystems/devpts.txt (next patch)
- Make ptmx node even in init_pts_ns, now that default mode is 0000
(defined in earlier patch, enabled here).
- Cache ptmx dentry and use to update mode during remount
(defined in earlier patch, enabled here).
- Bugfix: explicitly ignore newinstance on remount (if newinstance was
specified on remount of initial mount, it would be ignored but
/proc/mounts would imply that the option was set)
Changelog[v4]:
- Update patch description to address H. Peter Anvin's comments
- Consolidate multi-instance mode code under new config token,
CONFIG_DEVPTS_MULTIPLE_INSTANCE.
- Move usage-details from patch description to
Documentation/fs/devpts.txt
Changelog[v3]:
- Rename new mount option to 'newinstance'
- Create ptmx nodes only in 'newinstance' mounts
- Bugfix: parse_mount_options() modifies @data but since we need to
parse the @data twice (once in devpts_get_sb() and once during
do_remount_sb()), parse a local copy of @data in devpts_get_sb().
(restructured code in devpts_get_sb() to fix this)
Changelog[v2]:
- Support both single-mount and multiple-mount semantics and
provide '-onewmnt' option to select the semantics.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-01-02 16:42:27 +03:00
|
|
|
if (op == PARSE_MOUNT)
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
opts->reserve =
|
|
|
|
(current->nsproxy->mnt_ns == init_task.nsproxy->mnt_ns);
|
Enable multiple instances of devpts
To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.
But to preserve backward compatibility, enable this support for multiple
instances only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
- '-o newinstance' mount option is specified while mounting devpts
To use multi-instance mount, a container startup script could:
$ ns_exec -cm /bin/bash
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ mount -o bind /dev/pts/ptmx /dev/ptmx
$ /usr/sbin/sshd -p 1234
where 'ns_exec -cm /bin/bash' is 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.
USER-SPACE-IMPACT:
- See Documentation/fs/devpts.txt (included in next patch) for user-
space impact in multi-instance and mixed-mode operation.
TODO:
- Update mount(8), pts(4) man pages. Highlight impact of not
redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.
Changelog[v6]:
- [Dave Hansen] Use new get_init_pts_sb() interface
- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
- [Serge Hallyn] Check error return from get_sb_single() (now
get_init_pts_sb())
- devpts_pty_kill(): don't dput error dentries
Changelog[v5]:
- Move get_sb_ref() definition to earlier patch
- Move usage info to Documentation/filesystems/devpts.txt (next patch)
- Make ptmx node even in init_pts_ns, now that default mode is 0000
(defined in earlier patch, enabled here).
- Cache ptmx dentry and use to update mode during remount
(defined in earlier patch, enabled here).
- Bugfix: explicitly ignore newinstance on remount (if newinstance was
specified on remount of initial mount, it would be ignored but
/proc/mounts would imply that the option was set)
Changelog[v4]:
- Update patch description to address H. Peter Anvin's comments
- Consolidate multi-instance mode code under new config token,
CONFIG_DEVPTS_MULTIPLE_INSTANCE.
- Move usage-details from patch description to
Documentation/fs/devpts.txt
Changelog[v3]:
- Rename new mount option to 'newinstance'
- Create ptmx nodes only in 'newinstance' mounts
- Bugfix: parse_mount_options() modifies @data but since we need to
parse the @data twice (once in devpts_get_sb() and once during
do_remount_sb()), parse a local copy of @data in devpts_get_sb().
(restructured code in devpts_get_sb() to fix this)
Changelog[v2]:
- Support both single-mount and multiple-mount semantics and
provide '-onewmnt' option to select the semantics.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-01-02 16:42:27 +03:00
|
|
|
|
2006-03-23 14:00:59 +03:00
|
|
|
while ((p = strsep(&data, ",")) != NULL) {
|
|
|
|
substring_t args[MAX_OPT_ARGS];
|
|
|
|
int token;
|
|
|
|
int option;
|
|
|
|
|
|
|
|
if (!*p)
|
2005-04-17 02:20:36 +04:00
|
|
|
continue;
|
2006-03-23 14:00:59 +03:00
|
|
|
|
|
|
|
token = match_token(p, tokens, args);
|
|
|
|
switch (token) {
|
|
|
|
case Opt_uid:
|
|
|
|
if (match_int(&args[0], &option))
|
|
|
|
return -EINVAL;
|
2012-02-08 04:22:56 +04:00
|
|
|
uid = make_kuid(current_user_ns(), option);
|
|
|
|
if (!uid_valid(uid))
|
|
|
|
return -EINVAL;
|
|
|
|
opts->uid = uid;
|
2009-01-02 16:41:33 +03:00
|
|
|
opts->setuid = 1;
|
2006-03-23 14:00:59 +03:00
|
|
|
break;
|
|
|
|
case Opt_gid:
|
|
|
|
if (match_int(&args[0], &option))
|
|
|
|
return -EINVAL;
|
2012-02-08 04:22:56 +04:00
|
|
|
gid = make_kgid(current_user_ns(), option);
|
|
|
|
if (!gid_valid(gid))
|
|
|
|
return -EINVAL;
|
|
|
|
opts->gid = gid;
|
2009-01-02 16:41:33 +03:00
|
|
|
opts->setgid = 1;
|
2006-03-23 14:00:59 +03:00
|
|
|
break;
|
|
|
|
case Opt_mode:
|
|
|
|
if (match_octal(&args[0], &option))
|
|
|
|
return -EINVAL;
|
2009-01-02 16:41:33 +03:00
|
|
|
opts->mode = option & S_IALLUGO;
|
2006-03-23 14:00:59 +03:00
|
|
|
break;
|
2009-01-02 16:42:02 +03:00
|
|
|
case Opt_ptmxmode:
|
|
|
|
if (match_octal(&args[0], &option))
|
|
|
|
return -EINVAL;
|
|
|
|
opts->ptmxmode = option & S_IALLUGO;
|
|
|
|
break;
|
Enable multiple instances of devpts
To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.
But to preserve backward compatibility, enable this support for multiple
instances only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
- '-o newinstance' mount option is specified while mounting devpts
To use multi-instance mount, a container startup script could:
$ ns_exec -cm /bin/bash
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ mount -o bind /dev/pts/ptmx /dev/ptmx
$ /usr/sbin/sshd -p 1234
where 'ns_exec -cm /bin/bash' is 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.
USER-SPACE-IMPACT:
- See Documentation/fs/devpts.txt (included in next patch) for user-
space impact in multi-instance and mixed-mode operation.
TODO:
- Update mount(8), pts(4) man pages. Highlight impact of not
redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.
Changelog[v6]:
- [Dave Hansen] Use new get_init_pts_sb() interface
- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
- [Serge Hallyn] Check error return from get_sb_single() (now
get_init_pts_sb())
- devpts_pty_kill(): don't dput error dentries
Changelog[v5]:
- Move get_sb_ref() definition to earlier patch
- Move usage info to Documentation/filesystems/devpts.txt (next patch)
- Make ptmx node even in init_pts_ns, now that default mode is 0000
(defined in earlier patch, enabled here).
- Cache ptmx dentry and use to update mode during remount
(defined in earlier patch, enabled here).
- Bugfix: explicitly ignore newinstance on remount (if newinstance was
specified on remount of initial mount, it would be ignored but
/proc/mounts would imply that the option was set)
Changelog[v4]:
- Update patch description to address H. Peter Anvin's comments
- Consolidate multi-instance mode code under new config token,
CONFIG_DEVPTS_MULTIPLE_INSTANCE.
- Move usage-details from patch description to
Documentation/fs/devpts.txt
Changelog[v3]:
- Rename new mount option to 'newinstance'
- Create ptmx nodes only in 'newinstance' mounts
- Bugfix: parse_mount_options() modifies @data but since we need to
parse the @data twice (once in devpts_get_sb() and once during
do_remount_sb()), parse a local copy of @data in devpts_get_sb().
(restructured code in devpts_get_sb() to fix this)
Changelog[v2]:
- Support both single-mount and multiple-mount semantics and
provide '-onewmnt' option to select the semantics.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-01-02 16:42:27 +03:00
|
|
|
case Opt_newinstance:
|
|
|
|
break;
|
2012-01-05 13:06:11 +04:00
|
|
|
case Opt_max:
|
|
|
|
if (match_int(&args[0], &option) ||
|
|
|
|
option < 0 || option > NR_UNIX98_PTY_MAX)
|
|
|
|
return -EINVAL;
|
|
|
|
opts->max = option;
|
|
|
|
break;
|
2006-03-23 14:00:59 +03:00
|
|
|
default:
|
2014-06-07 01:37:34 +04:00
|
|
|
pr_err("called with bogus options\n");
|
2005-04-17 02:20:36 +04:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-01-02 16:42:02 +03:00
|
|
|
static int mknod_ptmx(struct super_block *sb)
|
|
|
|
{
|
|
|
|
int mode;
|
|
|
|
int rc = -ENOMEM;
|
|
|
|
struct dentry *dentry;
|
|
|
|
struct inode *inode;
|
|
|
|
struct dentry *root = sb->s_root;
|
|
|
|
struct pts_fs_info *fsi = DEVPTS_SB(sb);
|
|
|
|
struct pts_mount_opts *opts = &fsi->mount_opts;
|
2016-09-14 21:53:38 +03:00
|
|
|
kuid_t ptmx_uid = current_fsuid();
|
|
|
|
kgid_t ptmx_gid = current_fsgid();
|
2009-01-02 16:42:02 +03:00
|
|
|
|
2016-01-22 23:40:57 +03:00
|
|
|
inode_lock(d_inode(root));
|
2009-01-02 16:42:02 +03:00
|
|
|
|
|
|
|
/* If we have already created ptmx node, return */
|
|
|
|
if (fsi->ptmx_dentry) {
|
|
|
|
rc = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
dentry = d_alloc_name(root, "ptmx");
|
|
|
|
if (!dentry) {
|
2014-06-07 01:37:34 +04:00
|
|
|
pr_err("Unable to alloc dentry for ptmx node\n");
|
2009-01-02 16:42:02 +03:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a new 'ptmx' node in this mount of devpts.
|
|
|
|
*/
|
|
|
|
inode = new_inode(sb);
|
|
|
|
if (!inode) {
|
2014-06-07 01:37:34 +04:00
|
|
|
pr_err("Unable to alloc inode for ptmx node\n");
|
2009-01-02 16:42:02 +03:00
|
|
|
dput(dentry);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
inode->i_ino = 2;
|
2016-09-14 17:48:04 +03:00
|
|
|
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
|
2009-01-02 16:42:02 +03:00
|
|
|
|
|
|
|
mode = S_IFCHR|opts->ptmxmode;
|
|
|
|
init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));
|
2016-09-14 21:53:38 +03:00
|
|
|
inode->i_uid = ptmx_uid;
|
|
|
|
inode->i_gid = ptmx_gid;
|
2009-01-02 16:42:02 +03:00
|
|
|
|
|
|
|
d_add(dentry, inode);
|
|
|
|
|
|
|
|
fsi->ptmx_dentry = dentry;
|
|
|
|
rc = 0;
|
|
|
|
out:
|
2016-01-22 23:40:57 +03:00
|
|
|
inode_unlock(d_inode(root));
|
2009-01-02 16:42:02 +03:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void update_ptmx_mode(struct pts_fs_info *fsi)
|
|
|
|
{
|
|
|
|
struct inode *inode;
|
|
|
|
if (fsi->ptmx_dentry) {
|
2015-03-18 01:25:59 +03:00
|
|
|
inode = d_inode(fsi->ptmx_dentry);
|
2009-01-02 16:42:02 +03:00
|
|
|
inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-02 16:41:47 +03:00
|
|
|
static int devpts_remount(struct super_block *sb, int *flags, char *data)
|
|
|
|
{
|
2009-01-02 16:42:02 +03:00
|
|
|
int err;
|
2009-01-02 16:41:47 +03:00
|
|
|
struct pts_fs_info *fsi = DEVPTS_SB(sb);
|
|
|
|
struct pts_mount_opts *opts = &fsi->mount_opts;
|
|
|
|
|
Enable multiple instances of devpts
To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.
But to preserve backward compatibility, enable this support for multiple
instances only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
- '-o newinstance' mount option is specified while mounting devpts
To use multi-instance mount, a container startup script could:
$ ns_exec -cm /bin/bash
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ mount -o bind /dev/pts/ptmx /dev/ptmx
$ /usr/sbin/sshd -p 1234
where 'ns_exec -cm /bin/bash' is 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.
USER-SPACE-IMPACT:
- See Documentation/fs/devpts.txt (included in next patch) for user-
space impact in multi-instance and mixed-mode operation.
TODO:
- Update mount(8), pts(4) man pages. Highlight impact of not
redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.
Changelog[v6]:
- [Dave Hansen] Use new get_init_pts_sb() interface
- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
- [Serge Hallyn] Check error return from get_sb_single() (now
get_init_pts_sb())
- devpts_pty_kill(): don't dput error dentries
Changelog[v5]:
- Move get_sb_ref() definition to earlier patch
- Move usage info to Documentation/filesystems/devpts.txt (next patch)
- Make ptmx node even in init_pts_ns, now that default mode is 0000
(defined in earlier patch, enabled here).
- Cache ptmx dentry and use to update mode during remount
(defined in earlier patch, enabled here).
- Bugfix: explicitly ignore newinstance on remount (if newinstance was
specified on remount of initial mount, it would be ignored but
/proc/mounts would imply that the option was set)
Changelog[v4]:
- Update patch description to address H. Peter Anvin's comments
- Consolidate multi-instance mode code under new config token,
CONFIG_DEVPTS_MULTIPLE_INSTANCE.
- Move usage-details from patch description to
Documentation/fs/devpts.txt
Changelog[v3]:
- Rename new mount option to 'newinstance'
- Create ptmx nodes only in 'newinstance' mounts
- Bugfix: parse_mount_options() modifies @data but since we need to
parse the @data twice (once in devpts_get_sb() and once during
do_remount_sb()), parse a local copy of @data in devpts_get_sb().
(restructured code in devpts_get_sb() to fix this)
Changelog[v2]:
- Support both single-mount and multiple-mount semantics and
provide '-onewmnt' option to select the semantics.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-01-02 16:42:27 +03:00
|
|
|
err = parse_mount_options(data, PARSE_REMOUNT, opts);
|
2009-01-02 16:42:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* parse_mount_options() restores options to default values
|
|
|
|
* before parsing and may have changed ptmxmode. So, update the
|
|
|
|
* mode in the inode too. Bogus options don't fail the remount,
|
|
|
|
* so do this even on error return.
|
|
|
|
*/
|
|
|
|
update_ptmx_mode(fsi);
|
|
|
|
|
|
|
|
return err;
|
2009-01-02 16:41:47 +03:00
|
|
|
}
|
|
|
|
|
2011-12-09 06:32:45 +04:00
|
|
|
static int devpts_show_options(struct seq_file *seq, struct dentry *root)
|
2008-02-08 15:21:41 +03:00
|
|
|
{
|
2011-12-09 06:32:45 +04:00
|
|
|
struct pts_fs_info *fsi = DEVPTS_SB(root->d_sb);
|
2009-01-02 16:41:33 +03:00
|
|
|
struct pts_mount_opts *opts = &fsi->mount_opts;
|
|
|
|
|
|
|
|
if (opts->setuid)
|
2014-06-07 01:37:34 +04:00
|
|
|
seq_printf(seq, ",uid=%u",
|
|
|
|
from_kuid_munged(&init_user_ns, opts->uid));
|
2009-01-02 16:41:33 +03:00
|
|
|
if (opts->setgid)
|
2014-06-07 01:37:34 +04:00
|
|
|
seq_printf(seq, ",gid=%u",
|
|
|
|
from_kgid_munged(&init_user_ns, opts->gid));
|
2009-01-02 16:41:33 +03:00
|
|
|
seq_printf(seq, ",mode=%03o", opts->mode);
|
2009-01-02 16:42:02 +03:00
|
|
|
seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
|
2012-01-05 13:06:11 +04:00
|
|
|
if (opts->max < NR_UNIX98_PTY_MAX)
|
|
|
|
seq_printf(seq, ",max=%d", opts->max);
|
2008-02-08 15:21:41 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-02-12 11:55:41 +03:00
|
|
|
static const struct super_operations devpts_sops = {
|
2005-04-17 02:20:36 +04:00
|
|
|
.statfs = simple_statfs,
|
|
|
|
.remount_fs = devpts_remount,
|
2008-02-08 15:21:41 +03:00
|
|
|
.show_options = devpts_show_options,
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
devpts: clean up interface to pty drivers
This gets rid of the horrible notion of having that
struct inode *ptmx_inode
be the linchpin of the interface between the pty code and devpts.
By de-emphasizing the ptmx inode, a lot of things actually get cleaner,
and we will have a much saner way forward. In particular, this will
allow us to associate with any particular devpts instance at open-time,
and not be artificially tied to one particular ptmx inode.
The patch itself is actually fairly straightforward, and apart from some
locking and return path cleanups it's pretty mechanical:
- the interfaces that devpts exposes all take "struct pts_fs_info *"
instead of "struct inode *ptmx_inode" now.
NOTE! The "struct pts_fs_info" thing is a completely opaque structure
as far as the pty driver is concerned: it's still declared entirely
internally to devpts. So the pty code can't actually access it in any
way, just pass it as a "cookie" to the devpts code.
- the "look up the pts fs info" is now a single clear operation, that
also does the reference count increment on the pts superblock.
So "devpts_add/del_ref()" is gone, and replaced by a "lookup and get
ref" operation (devpts_get_ref(inode)), along with a "put ref" op
(devpts_put_ref()).
- the pty master "tty->driver_data" field now contains the pts_fs_info,
not the ptmx inode.
- because we don't care about the ptmx inode any more as some kind of
base index, the ref counting can now drop the inode games - it just
gets the ref on the superblock.
- the pts_fs_info now has a back-pointer to the super_block. That's so
that we can easily look up the information we actually need. Although
quite often, the pts fs info was actually all we wanted, and not having
to look it up based on some magical inode makes things more
straightforward.
In particular, now that "devpts_get_ref(inode)" operation should really
be the *only* place we need to look up what devpts instance we're
associated with, and we do it exactly once, at ptmx_open() time.
The other side of this is that one ptmx node could now be associated
with multiple different devpts instances - you could have a single
/dev/ptmx node, and then have multiple mount namespaces with their own
instances of devpts mounted on /dev/pts/. And that's all perfectly sane
in a model where we just look up the pts instance at open time.
This will eventually allow us to get rid of our odd single-vs-multiple
pts instance model, but this patch in itself changes no semantics, only
an internal binding model.
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Greg KH <greg@kroah.com>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-17 01:16:07 +03:00
|
|
|
static void *new_pts_fs_info(struct super_block *sb)
|
2009-01-02 16:41:21 +03:00
|
|
|
{
|
|
|
|
struct pts_fs_info *fsi;
|
|
|
|
|
|
|
|
fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL);
|
|
|
|
if (!fsi)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ida_init(&fsi->allocated_ptys);
|
2009-01-02 16:41:33 +03:00
|
|
|
fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
|
2009-01-02 16:42:02 +03:00
|
|
|
fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
|
devpts: clean up interface to pty drivers
This gets rid of the horrible notion of having that
struct inode *ptmx_inode
be the linchpin of the interface between the pty code and devpts.
By de-emphasizing the ptmx inode, a lot of things actually get cleaner,
and we will have a much saner way forward. In particular, this will
allow us to associate with any particular devpts instance at open-time,
and not be artificially tied to one particular ptmx inode.
The patch itself is actually fairly straightforward, and apart from some
locking and return path cleanups it's pretty mechanical:
- the interfaces that devpts exposes all take "struct pts_fs_info *"
instead of "struct inode *ptmx_inode" now.
NOTE! The "struct pts_fs_info" thing is a completely opaque structure
as far as the pty driver is concerned: it's still declared entirely
internally to devpts. So the pty code can't actually access it in any
way, just pass it as a "cookie" to the devpts code.
- the "look up the pts fs info" is now a single clear operation, that
also does the reference count increment on the pts superblock.
So "devpts_add/del_ref()" is gone, and replaced by a "lookup and get
ref" operation (devpts_get_ref(inode)), along with a "put ref" op
(devpts_put_ref()).
- the pty master "tty->driver_data" field now contains the pts_fs_info,
not the ptmx inode.
- because we don't care about the ptmx inode any more as some kind of
base index, the ref counting can now drop the inode games - it just
gets the ref on the superblock.
- the pts_fs_info now has a back-pointer to the super_block. That's so
that we can easily look up the information we actually need. Although
quite often, the pts fs info was actually all we wanted, and not having
to look it up based on some magical inode makes things more
straightforward.
In particular, now that "devpts_get_ref(inode)" operation should really
be the *only* place we need to look up what devpts instance we're
associated with, and we do it exactly once, at ptmx_open() time.
The other side of this is that one ptmx node could now be associated
with multiple different devpts instances - you could have a single
/dev/ptmx node, and then have multiple mount namespaces with their own
instances of devpts mounted on /dev/pts/. And that's all perfectly sane
in a model where we just look up the pts instance at open time.
This will eventually allow us to get rid of our odd single-vs-multiple
pts instance model, but this patch in itself changes no semantics, only
an internal binding model.
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Greg KH <greg@kroah.com>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-17 01:16:07 +03:00
|
|
|
fsi->sb = sb;
|
2009-01-02 16:41:21 +03:00
|
|
|
|
|
|
|
return fsi;
|
|
|
|
}
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
static int
|
|
|
|
devpts_fill_super(struct super_block *s, void *data, int silent)
|
|
|
|
{
|
2009-01-02 16:42:02 +03:00
|
|
|
struct inode *inode;
|
2016-09-14 21:53:33 +03:00
|
|
|
int error;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2016-06-09 23:44:48 +03:00
|
|
|
s->s_iflags &= ~SB_I_NODEV;
|
2005-04-17 02:20:36 +04:00
|
|
|
s->s_blocksize = 1024;
|
|
|
|
s->s_blocksize_bits = 10;
|
|
|
|
s->s_magic = DEVPTS_SUPER_MAGIC;
|
|
|
|
s->s_op = &devpts_sops;
|
|
|
|
s->s_time_gran = 1;
|
|
|
|
|
2016-09-14 21:53:33 +03:00
|
|
|
error = -ENOMEM;
|
devpts: clean up interface to pty drivers
This gets rid of the horrible notion of having that
struct inode *ptmx_inode
be the linchpin of the interface between the pty code and devpts.
By de-emphasizing the ptmx inode, a lot of things actually get cleaner,
and we will have a much saner way forward. In particular, this will
allow us to associate with any particular devpts instance at open-time,
and not be artificially tied to one particular ptmx inode.
The patch itself is actually fairly straightforward, and apart from some
locking and return path cleanups it's pretty mechanical:
- the interfaces that devpts exposes all take "struct pts_fs_info *"
instead of "struct inode *ptmx_inode" now.
NOTE! The "struct pts_fs_info" thing is a completely opaque structure
as far as the pty driver is concerned: it's still declared entirely
internally to devpts. So the pty code can't actually access it in any
way, just pass it as a "cookie" to the devpts code.
- the "look up the pts fs info" is now a single clear operation, that
also does the reference count increment on the pts superblock.
So "devpts_add/del_ref()" is gone, and replaced by a "lookup and get
ref" operation (devpts_get_ref(inode)), along with a "put ref" op
(devpts_put_ref()).
- the pty master "tty->driver_data" field now contains the pts_fs_info,
not the ptmx inode.
- because we don't care about the ptmx inode any more as some kind of
base index, the ref counting can now drop the inode games - it just
gets the ref on the superblock.
- the pts_fs_info now has a back-pointer to the super_block. That's so
that we can easily look up the information we actually need. Although
quite often, the pts fs info was actually all we wanted, and not having
to look it up based on some magical inode makes things more
straightforward.
In particular, now that "devpts_get_ref(inode)" operation should really
be the *only* place we need to look up what devpts instance we're
associated with, and we do it exactly once, at ptmx_open() time.
The other side of this is that one ptmx node could now be associated
with multiple different devpts instances - you could have a single
/dev/ptmx node, and then have multiple mount namespaces with their own
instances of devpts mounted on /dev/pts/. And that's all perfectly sane
in a model where we just look up the pts instance at open time.
This will eventually allow us to get rid of our odd single-vs-multiple
pts instance model, but this patch in itself changes no semantics, only
an internal binding model.
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Greg KH <greg@kroah.com>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-17 01:16:07 +03:00
|
|
|
s->s_fs_info = new_pts_fs_info(s);
|
2009-01-02 16:41:21 +03:00
|
|
|
if (!s->s_fs_info)
|
|
|
|
goto fail;
|
|
|
|
|
2016-09-14 21:53:33 +03:00
|
|
|
error = parse_mount_options(data, PARSE_MOUNT, &DEVPTS_SB(s)->mount_opts);
|
|
|
|
if (error)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
error = -ENOMEM;
|
2005-04-17 02:20:36 +04:00
|
|
|
inode = new_inode(s);
|
|
|
|
if (!inode)
|
2012-01-09 04:40:27 +04:00
|
|
|
goto fail;
|
2005-04-17 02:20:36 +04:00
|
|
|
inode->i_ino = 1;
|
2016-09-14 17:48:04 +03:00
|
|
|
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
|
2005-04-17 02:20:36 +04:00
|
|
|
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
|
|
|
|
inode->i_op = &simple_dir_inode_operations;
|
|
|
|
inode->i_fop = &simple_dir_operations;
|
2011-10-28 16:13:29 +04:00
|
|
|
set_nlink(inode, 2);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2012-01-09 07:15:13 +04:00
|
|
|
s->s_root = d_make_root(inode);
|
2016-09-14 21:53:34 +03:00
|
|
|
if (!s->s_root) {
|
|
|
|
pr_err("get root dentry failed\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
2009-01-02 16:42:02 +03:00
|
|
|
|
2016-09-14 21:53:34 +03:00
|
|
|
error = mknod_ptmx(s);
|
|
|
|
if (error)
|
|
|
|
goto fail_dput;
|
2009-01-02 16:41:21 +03:00
|
|
|
|
2016-09-14 21:53:34 +03:00
|
|
|
return 0;
|
|
|
|
fail_dput:
|
|
|
|
dput(s->s_root);
|
|
|
|
s->s_root = NULL;
|
2005-04-17 02:20:36 +04:00
|
|
|
fail:
|
2016-09-14 21:53:33 +03:00
|
|
|
return error;
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
Enable multiple instances of devpts
To support containers, allow multiple instances of devpts filesystem, such
that indices of ptys allocated in one instance are independent of ptys
allocated in other instances of devpts.
But to preserve backward compatibility, enable this support for multiple
instances only if:
- CONFIG_DEVPTS_MULTIPLE_INSTANCES is set to Y, and
- '-o newinstance' mount option is specified while mounting devpts
To use multi-instance mount, a container startup script could:
$ ns_exec -cm /bin/bash
$ umount /dev/pts
$ mount -t devpts -o newinstance lxcpts /dev/pts
$ mount -o bind /dev/pts/ptmx /dev/ptmx
$ /usr/sbin/sshd -p 1234
where 'ns_exec -cm /bin/bash' is 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.
USER-SPACE-IMPACT:
- See Documentation/fs/devpts.txt (included in next patch) for user-
space impact in multi-instance and mixed-mode operation.
TODO:
- Update mount(8), pts(4) man pages. Highlight impact of not
redirecting /dev/ptmx to /dev/pts/ptmx after a multi-instance mount.
Changelog[v6]:
- [Dave Hansen] Use new get_init_pts_sb() interface
- [Serge Hallyn] Don't bother displaying 'newinstance' in show_options
- [Serge Hallyn] Use macros (PARSE_REMOUNT/PARSE_MOUNT) instead of 0/1.
- [Serge Hallyn] Check error return from get_sb_single() (now
get_init_pts_sb())
- devpts_pty_kill(): don't dput error dentries
Changelog[v5]:
- Move get_sb_ref() definition to earlier patch
- Move usage info to Documentation/filesystems/devpts.txt (next patch)
- Make ptmx node even in init_pts_ns, now that default mode is 0000
(defined in earlier patch, enabled here).
- Cache ptmx dentry and use to update mode during remount
(defined in earlier patch, enabled here).
- Bugfix: explicitly ignore newinstance on remount (if newinstance was
specified on remount of initial mount, it would be ignored but
/proc/mounts would imply that the option was set)
Changelog[v4]:
- Update patch description to address H. Peter Anvin's comments
- Consolidate multi-instance mode code under new config token,
CONFIG_DEVPTS_MULTIPLE_INSTANCE.
- Move usage-details from patch description to
Documentation/fs/devpts.txt
Changelog[v3]:
- Rename new mount option to 'newinstance'
- Create ptmx nodes only in 'newinstance' mounts
- Bugfix: parse_mount_options() modifies @data but since we need to
parse the @data twice (once in devpts_get_sb() and once during
do_remount_sb()), parse a local copy of @data in devpts_get_sb().
(restructured code in devpts_get_sb() to fix this)
Changelog[v2]:
- Support both single-mount and multiple-mount semantics and
provide '-onewmnt' option to select the semantics.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-01-02 16:42:27 +03:00
|
|
|
/*
|
2010-07-25 01:48:30 +04:00
|
|
|
* devpts_mount()
|
2009-03-07 21:12:32 +03:00
|
|
|
*
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
* Mount a new (private) instance of devpts. PTYs created in this
|
|
|
|
* instance are independent of the PTYs in other devpts instances.
|
2009-01-02 16:42:19 +03:00
|
|
|
*/
|
2010-07-25 01:48:30 +04:00
|
|
|
static struct dentry *devpts_mount(struct file_system_type *fs_type,
|
|
|
|
int flags, const char *dev_name, void *data)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2016-09-14 21:53:35 +03:00
|
|
|
return mount_nodev(fs_type, flags, data, devpts_fill_super);
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
2009-03-07 21:14:41 +03:00
|
|
|
|
2009-01-02 16:41:21 +03:00
|
|
|
static void devpts_kill_sb(struct super_block *sb)
|
|
|
|
{
|
|
|
|
struct pts_fs_info *fsi = DEVPTS_SB(sb);
|
|
|
|
|
2016-09-14 21:53:36 +03:00
|
|
|
if (fsi)
|
|
|
|
ida_destroy(&fsi->allocated_ptys);
|
2009-01-02 16:41:21 +03:00
|
|
|
kfree(fsi);
|
2009-01-02 16:42:02 +03:00
|
|
|
kill_litter_super(sb);
|
2009-01-02 16:41:21 +03:00
|
|
|
}
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
static struct file_system_type devpts_fs_type = {
|
|
|
|
.name = "devpts",
|
2010-07-25 01:48:30 +04:00
|
|
|
.mount = devpts_mount,
|
2009-01-02 16:41:21 +03:00
|
|
|
.kill_sb = devpts_kill_sb,
|
2016-06-09 23:44:48 +03:00
|
|
|
.fs_flags = FS_USERNS_MOUNT,
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The normal naming convention is simply /dev/pts/<number>; this conforms
|
|
|
|
* to the System V naming convention
|
|
|
|
*/
|
|
|
|
|
devpts: clean up interface to pty drivers
This gets rid of the horrible notion of having that
struct inode *ptmx_inode
be the linchpin of the interface between the pty code and devpts.
By de-emphasizing the ptmx inode, a lot of things actually get cleaner,
and we will have a much saner way forward. In particular, this will
allow us to associate with any particular devpts instance at open-time,
and not be artificially tied to one particular ptmx inode.
The patch itself is actually fairly straightforward, and apart from some
locking and return path cleanups it's pretty mechanical:
- the interfaces that devpts exposes all take "struct pts_fs_info *"
instead of "struct inode *ptmx_inode" now.
NOTE! The "struct pts_fs_info" thing is a completely opaque structure
as far as the pty driver is concerned: it's still declared entirely
internally to devpts. So the pty code can't actually access it in any
way, just pass it as a "cookie" to the devpts code.
- the "look up the pts fs info" is now a single clear operation, that
also does the reference count increment on the pts superblock.
So "devpts_add/del_ref()" is gone, and replaced by a "lookup and get
ref" operation (devpts_get_ref(inode)), along with a "put ref" op
(devpts_put_ref()).
- the pty master "tty->driver_data" field now contains the pts_fs_info,
not the ptmx inode.
- because we don't care about the ptmx inode any more as some kind of
base index, the ref counting can now drop the inode games - it just
gets the ref on the superblock.
- the pts_fs_info now has a back-pointer to the super_block. That's so
that we can easily look up the information we actually need. Although
quite often, the pts fs info was actually all we wanted, and not having
to look it up based on some magical inode makes things more
straightforward.
In particular, now that "devpts_get_ref(inode)" operation should really
be the *only* place we need to look up what devpts instance we're
associated with, and we do it exactly once, at ptmx_open() time.
The other side of this is that one ptmx node could now be associated
with multiple different devpts instances - you could have a single
/dev/ptmx node, and then have multiple mount namespaces with their own
instances of devpts mounted on /dev/pts/. And that's all perfectly sane
in a model where we just look up the pts instance at open time.
This will eventually allow us to get rid of our odd single-vs-multiple
pts instance model, but this patch in itself changes no semantics, only
an internal binding model.
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Greg KH <greg@kroah.com>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-17 01:16:07 +03:00
|
|
|
int devpts_new_index(struct pts_fs_info *fsi)
|
2008-04-30 11:54:21 +04:00
|
|
|
{
|
|
|
|
int index;
|
2008-07-26 11:42:16 +04:00
|
|
|
int ida_ret;
|
2008-04-30 11:54:21 +04:00
|
|
|
|
|
|
|
retry:
|
2009-01-02 16:42:48 +03:00
|
|
|
if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
|
2008-04-30 11:54:21 +04:00
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
mutex_lock(&allocated_ptys_lock);
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
if (pty_count >= (pty_limit -
|
|
|
|
(fsi->mount_opts.reserve ? 0 : pty_reserve))) {
|
2012-01-05 13:06:11 +04:00
|
|
|
mutex_unlock(&allocated_ptys_lock);
|
|
|
|
return -ENOSPC;
|
|
|
|
}
|
|
|
|
|
2009-01-02 16:41:21 +03:00
|
|
|
ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
|
2008-07-26 11:42:16 +04:00
|
|
|
if (ida_ret < 0) {
|
2008-04-30 11:54:21 +04:00
|
|
|
mutex_unlock(&allocated_ptys_lock);
|
2008-07-26 11:42:16 +04:00
|
|
|
if (ida_ret == -EAGAIN)
|
2008-04-30 11:54:21 +04:00
|
|
|
goto retry;
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
2012-01-05 13:06:11 +04:00
|
|
|
if (index >= fsi->mount_opts.max) {
|
2009-01-02 16:41:21 +03:00
|
|
|
ida_remove(&fsi->allocated_ptys, index);
|
2008-04-30 11:54:21 +04:00
|
|
|
mutex_unlock(&allocated_ptys_lock);
|
2012-01-05 13:06:11 +04:00
|
|
|
return -ENOSPC;
|
2008-04-30 11:54:21 +04:00
|
|
|
}
|
2012-01-05 13:06:02 +04:00
|
|
|
pty_count++;
|
2008-04-30 11:54:21 +04:00
|
|
|
mutex_unlock(&allocated_ptys_lock);
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
devpts: clean up interface to pty drivers
This gets rid of the horrible notion of having that
struct inode *ptmx_inode
be the linchpin of the interface between the pty code and devpts.
By de-emphasizing the ptmx inode, a lot of things actually get cleaner,
and we will have a much saner way forward. In particular, this will
allow us to associate with any particular devpts instance at open-time,
and not be artificially tied to one particular ptmx inode.
The patch itself is actually fairly straightforward, and apart from some
locking and return path cleanups it's pretty mechanical:
- the interfaces that devpts exposes all take "struct pts_fs_info *"
instead of "struct inode *ptmx_inode" now.
NOTE! The "struct pts_fs_info" thing is a completely opaque structure
as far as the pty driver is concerned: it's still declared entirely
internally to devpts. So the pty code can't actually access it in any
way, just pass it as a "cookie" to the devpts code.
- the "look up the pts fs info" is now a single clear operation, that
also does the reference count increment on the pts superblock.
So "devpts_add/del_ref()" is gone, and replaced by a "lookup and get
ref" operation (devpts_get_ref(inode)), along with a "put ref" op
(devpts_put_ref()).
- the pty master "tty->driver_data" field now contains the pts_fs_info,
not the ptmx inode.
- because we don't care about the ptmx inode any more as some kind of
base index, the ref counting can now drop the inode games - it just
gets the ref on the superblock.
- the pts_fs_info now has a back-pointer to the super_block. That's so
that we can easily look up the information we actually need. Although
quite often, the pts fs info was actually all we wanted, and not having
to look it up based on some magical inode makes things more
straightforward.
In particular, now that "devpts_get_ref(inode)" operation should really
be the *only* place we need to look up what devpts instance we're
associated with, and we do it exactly once, at ptmx_open() time.
The other side of this is that one ptmx node could now be associated
with multiple different devpts instances - you could have a single
/dev/ptmx node, and then have multiple mount namespaces with their own
instances of devpts mounted on /dev/pts/. And that's all perfectly sane
in a model where we just look up the pts instance at open time.
This will eventually allow us to get rid of our odd single-vs-multiple
pts instance model, but this patch in itself changes no semantics, only
an internal binding model.
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Greg KH <greg@kroah.com>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-17 01:16:07 +03:00
|
|
|
void devpts_kill_index(struct pts_fs_info *fsi, int idx)
|
2008-04-30 11:54:21 +04:00
|
|
|
{
|
|
|
|
mutex_lock(&allocated_ptys_lock);
|
2009-01-02 16:41:21 +03:00
|
|
|
ida_remove(&fsi->allocated_ptys, idx);
|
2012-01-05 13:06:02 +04:00
|
|
|
pty_count--;
|
2008-04-30 11:54:21 +04:00
|
|
|
mutex_unlock(&allocated_ptys_lock);
|
|
|
|
}
|
|
|
|
|
2012-10-19 00:26:30 +04:00
|
|
|
/**
|
|
|
|
* devpts_pty_new -- create a new inode in /dev/pts/
|
|
|
|
* @ptmx_inode: inode of the master
|
|
|
|
* @device: major+minor of the node to be created
|
|
|
|
* @index: used as a name of the node
|
|
|
|
* @priv: what's given back by devpts_get_priv
|
|
|
|
*
|
|
|
|
* The created inode is returned. Remove it from /dev/pts/ by devpts_pty_kill.
|
|
|
|
*/
|
2016-04-26 06:04:08 +03:00
|
|
|
struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
|
|
|
struct dentry *dentry;
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
struct super_block *sb = fsi->sb;
|
2012-10-19 00:26:28 +04:00
|
|
|
struct inode *inode;
|
2015-07-01 00:58:27 +03:00
|
|
|
struct dentry *root;
|
|
|
|
struct pts_mount_opts *opts;
|
2008-10-13 13:43:18 +04:00
|
|
|
char s[12];
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2015-07-01 00:58:27 +03:00
|
|
|
root = sb->s_root;
|
|
|
|
opts = &fsi->mount_opts;
|
|
|
|
|
2012-10-19 00:26:28 +04:00
|
|
|
inode = new_inode(sb);
|
2005-04-17 02:20:36 +04:00
|
|
|
if (!inode)
|
2012-10-19 00:26:28 +04:00
|
|
|
return ERR_PTR(-ENOMEM);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2012-10-19 00:26:29 +04:00
|
|
|
inode->i_ino = index + 3;
|
2009-01-02 16:44:49 +03:00
|
|
|
inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
|
|
|
|
inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
|
2016-09-14 17:48:04 +03:00
|
|
|
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
|
2016-04-26 06:04:08 +03:00
|
|
|
init_special_inode(inode, S_IFCHR|opts->mode, MKDEV(UNIX98_PTY_SLAVE_MAJOR, index));
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2012-10-19 00:26:29 +04:00
|
|
|
sprintf(s, "%d", index);
|
2008-10-13 13:43:18 +04:00
|
|
|
|
2009-01-02 16:41:11 +03:00
|
|
|
dentry = d_alloc_name(root, s);
|
2011-03-23 02:35:11 +03:00
|
|
|
if (dentry) {
|
2016-04-26 06:04:08 +03:00
|
|
|
dentry->d_fsdata = priv;
|
2008-10-13 13:43:18 +04:00
|
|
|
d_add(dentry, inode);
|
2015-03-18 01:25:59 +03:00
|
|
|
fsnotify_create(d_inode(root), dentry);
|
2011-02-08 00:14:52 +03:00
|
|
|
} else {
|
|
|
|
iput(inode);
|
2016-04-26 06:04:08 +03:00
|
|
|
dentry = ERR_PTR(-ENOMEM);
|
2007-05-08 11:24:18 +04:00
|
|
|
}
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2016-04-26 06:04:08 +03:00
|
|
|
return dentry;
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
2012-10-19 00:26:30 +04:00
|
|
|
/**
|
|
|
|
* devpts_get_priv -- get private data for a slave
|
|
|
|
* @pts_inode: inode of the slave
|
|
|
|
*
|
|
|
|
* Returns whatever was passed as priv in devpts_pty_new for a given inode.
|
|
|
|
*/
|
2016-04-26 06:04:08 +03:00
|
|
|
void *devpts_get_priv(struct dentry *dentry)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2016-09-03 21:02:50 +03:00
|
|
|
if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC)
|
|
|
|
return NULL;
|
2016-04-26 06:04:08 +03:00
|
|
|
return dentry->d_fsdata;
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
2012-10-19 00:26:30 +04:00
|
|
|
/**
|
|
|
|
* devpts_pty_kill -- remove inode form /dev/pts/
|
|
|
|
* @inode: inode of the slave to be removed
|
|
|
|
*
|
|
|
|
* This is an inverse operation of devpts_pty_new.
|
|
|
|
*/
|
2016-04-26 06:04:08 +03:00
|
|
|
void devpts_pty_kill(struct dentry *dentry)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2016-04-26 06:04:08 +03:00
|
|
|
WARN_ON_ONCE(dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2016-04-26 06:04:08 +03:00
|
|
|
dentry->d_fsdata = NULL;
|
|
|
|
drop_nlink(dentry->d_inode);
|
2011-02-08 00:14:52 +03:00
|
|
|
d_delete(dentry);
|
|
|
|
dput(dentry); /* d_alloc_name() in devpts_pty_new() */
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int __init init_devpts_fs(void)
|
|
|
|
{
|
|
|
|
int err = register_filesystem(&devpts_fs_type);
|
|
|
|
if (!err) {
|
devpts: Make each mount of devpts an independent filesystem.
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>
Cc: Greg KH <greg@kroah.com>
Cc: Peter Hurley <peter@hurleysoftware.com>
Cc: Peter Anvin <hpa@zytor.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Jann Horn <jann@thejh.net>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Florian Weimer <fw@deneb.enyo.de>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-06-02 18:29:47 +03:00
|
|
|
register_sysctl_table(pty_root_table);
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
module_init(init_devpts_fs)
|