aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-08-16 20:08:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-08-17 12:10:48 -0400
commitc8c03f1858331e85d397bacccd34ef409aae993c (patch)
tree02e36380538407e87ebd5b523c79851f7549d6c9 /fs
parentac9a40905a610fb02086a37b11ff4bf046825a88 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/devpts/inode.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 108df2e3602c..44dfbca9306f 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -133,7 +133,7 @@ static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
133 return sb->s_fs_info; 133 return sb->s_fs_info;
134} 134}
135 135
136struct pts_fs_info *devpts_acquire(struct file *filp) 136struct pts_fs_info *devpts_acquire(struct file *filp, struct vfsmount **ptsmnt)
137{ 137{
138 struct pts_fs_info *result; 138 struct pts_fs_info *result;
139 struct path path; 139 struct path path;
@@ -142,6 +142,7 @@ struct pts_fs_info *devpts_acquire(struct file *filp)
142 142
143 path = filp->f_path; 143 path = filp->f_path;
144 path_get(&path); 144 path_get(&path);
145 *ptsmnt = NULL;
145 146
146 /* Has the devpts filesystem already been found? */ 147 /* Has the devpts filesystem already been found? */
147 sb = path.mnt->mnt_sb; 148 sb = path.mnt->mnt_sb;
@@ -165,6 +166,7 @@ struct pts_fs_info *devpts_acquire(struct file *filp)
165 * pty code needs to hold extra references in case of last /dev/tty close 166 * pty code needs to hold extra references in case of last /dev/tty close
166 */ 167 */
167 atomic_inc(&sb->s_active); 168 atomic_inc(&sb->s_active);
169 *ptsmnt = mntget(path.mnt);
168 result = DEVPTS_SB(sb); 170 result = DEVPTS_SB(sb);
169 171
170out: 172out: