From: Greg Kroah-Hartman Date: Fri, 13 Jul 2018 13:24:09 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.4.141~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=151e0bcaf9ee472e5fbf6cd4b5a52a9ba00ac843;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: devpts-hoist-out-check-for-devpts_super_magic.patch devpts-resolve-devpts-bind-mounts.patch --- diff --git a/queue-4.14/devpts-hoist-out-check-for-devpts_super_magic.patch b/queue-4.14/devpts-hoist-out-check-for-devpts_super_magic.patch new file mode 100644 index 00000000000..6a952f901c7 --- /dev/null +++ b/queue-4.14/devpts-hoist-out-check-for-devpts_super_magic.patch @@ -0,0 +1,88 @@ +From 7d71109df186d630a41280670c8d71d0cf9b0da9 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Tue, 13 Mar 2018 17:55:24 +0100 +Subject: devpts: hoist out check for DEVPTS_SUPER_MAGIC + +From: Christian Brauner + +commit 7d71109df186d630a41280670c8d71d0cf9b0da9 upstream. + +Hoist the check whether we have already found a suitable devpts filesystem +out of devpts_ptmx_path() in preparation for the devpts bind-mount +resolution patch. This is a non-functional change. + +Signed-off-by: Christian Brauner +Reviewed-by: "Eric W. Biederman" +Acked-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/devpts/inode.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -138,10 +138,6 @@ static int devpts_ptmx_path(struct path + struct super_block *sb; + int err; + +- /* Has the devpts filesystem already been found? */ +- if (path->mnt->mnt_sb->s_magic == DEVPTS_SUPER_MAGIC) +- return 0; +- + /* Is a devpts filesystem at "pts" in the same directory? */ + err = path_pts(path); + if (err) +@@ -159,21 +155,25 @@ static int devpts_ptmx_path(struct path + struct vfsmount *devpts_mntget(struct file *filp, struct pts_fs_info *fsi) + { + struct path path; +- int err; ++ int err = 0; + + path = filp->f_path; + path_get(&path); + +- err = devpts_ptmx_path(&path); ++ /* Has the devpts filesystem already been found? */ ++ if (path.mnt->mnt_sb->s_magic != DEVPTS_SUPER_MAGIC) ++ err = devpts_ptmx_path(&path); + dput(path.dentry); + if (err) { + mntput(path.mnt); + return ERR_PTR(err); + } ++ + if (DEVPTS_SB(path.mnt->mnt_sb) != fsi) { + mntput(path.mnt); + return ERR_PTR(-ENODEV); + } ++ + return path.mnt; + } + +@@ -182,15 +182,19 @@ struct pts_fs_info *devpts_acquire(struc + struct pts_fs_info *result; + struct path path; + struct super_block *sb; +- int err; + + path = filp->f_path; + path_get(&path); + +- err = devpts_ptmx_path(&path); +- if (err) { +- result = ERR_PTR(err); +- goto out; ++ /* Has the devpts filesystem already been found? */ ++ if (path.mnt->mnt_sb->s_magic != DEVPTS_SUPER_MAGIC) { ++ int err; ++ ++ err = devpts_ptmx_path(&path); ++ if (err) { ++ result = ERR_PTR(err); ++ goto out; ++ } + } + + /* diff --git a/queue-4.14/devpts-resolve-devpts-bind-mounts.patch b/queue-4.14/devpts-resolve-devpts-bind-mounts.patch new file mode 100644 index 00000000000..8fea6fe50ae --- /dev/null +++ b/queue-4.14/devpts-resolve-devpts-bind-mounts.patch @@ -0,0 +1,148 @@ +From a319b01d9095da6f6c54bd20c1f1300762506255 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Tue, 13 Mar 2018 17:55:25 +0100 +Subject: devpts: resolve devpts bind-mounts + +From: Christian Brauner + +commit a319b01d9095da6f6c54bd20c1f1300762506255 upstream. + +Most libcs will still look at /dev/ptmx when opening the master fd of a pty +device. When /dev/ptmx is a bind-mount of /dev/pts/ptmx and the TIOCGPTPEER +ioctl() is used to safely retrieve a file descriptor for the slave side of +the pty based on the master fd, the /proc/self/fd/{0,1,2} symlinks will +point to /. A very simply reproducer for this issue presupposing a libc +that uses TIOCGPTPEER in its openpty() implementation is: + +unshare --mount +mount --bind /dev/pts/ptmx /dev/ptmx +chmod 666 /dev/ptmx +script +ls -al /proc/self/fd/0 + +Having bind-mounts of /dev/pts/ptmx to /dev/ptmx not working correctly is a +regression. In addition, it is also a fairly common scenario in containers +employing user namespaces. + +The reason for the current failure is that the kernel tries to verify the +useability of the devpts filesystem without resolving the /dev/ptmx +bind-mount first. This will lead it to detect that the dentry is escaping +its bind-mount. The reason is that while the devpts filesystem mounted at +/dev/pts has the devtmpfs mounted at /dev as its parent mount: + +21 -- -- / /dev +-- 21 -- / /dev/pts + +devtmpfs and devpts are on different devices + +-- -- 0:6 / /dev +-- -- 0:20 / /dev/pts + +This has the consequence that the pathname of the parent directory of the +devpts filesystem mount at /dev/pts is /. So if /dev/ptmx is a bind-mount +of /dev/pts/ptmx then the /dev/ptmx bind-mount and the devpts mount at +/dev/pts will end up being located on the same device which is recorded in +the superblock of their vfsmount. This means the parent directory of the +/dev/ptmx bind-mount will be /ptmx: + +-- -- ---- /ptmx /dev/ptmx + +Without the bind-mount resolution patch the kernel will now perform the +bind-mount escape check directly on /dev/ptmx. The function responsible for +this is devpts_ptmx_path() which calls pts_path() which in turn calls +path_parent_directory(). Based on the above explanation, +path_parent_directory() will yield / as the parent directory for the +/dev/ptmx bind-mount and not the expected /dev. Thus, the kernel detects +that /dev/ptmx is escaping its bind-mount and will set /proc//fd/ +to /. + +This patch changes the logic to first resolve any bind-mounts. After the +bind-mounts have been resolved (i.e. we have traced it back to the +associated devpts mount) devpts_ptmx_path() can be called. In order to +guarantee correct path generation for the slave file descriptor the kernel +now requires that a pts directory is found in the parent directory of the +ptmx bind-mount. This implies that when doing bind-mounts the ptmx +bind-mount and the devpts mount should have a common parent directory. A +valid example is: + +mount -t devpts devpts /dev/pts +mount --bind /dev/pts/ptmx /dev/ptmx + +an invalid example is: + +mount -t devpts devpts /dev/pts +mount --bind /dev/pts/ptmx /ptmx + +This allows us to support: +- calling open on ptmx devices located inside non-standard devpts mounts: + mount -t devpts devpts /mnt + master = open("/mnt/ptmx", ...); + slave = ioctl(master, TIOCGPTPEER, ...); +- calling open on ptmx devices located outside the devpts mount with a + common ancestor directory: + mount -t devpts devpts /dev/pts + mount --bind /dev/pts/ptmx /dev/ptmx + master = open("/dev/ptmx", ...); + slave = ioctl(master, TIOCGPTPEER, ...); + +while failing on ptmx devices located outside the devpts mount without a +common ancestor directory: + mount -t devpts devpts /dev/pts + mount --bind /dev/pts/ptmx /ptmx + master = open("/ptmx", ...); + slave = ioctl(master, TIOCGPTPEER, ...); + +in which case save path generation cannot be guaranteed. + +Signed-off-by: Christian Brauner +Suggested-by: Eric Biederman +Suggested-by: Linus Torvalds +Reviewed-by: "Eric W. Biederman" +Acked-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + fs/devpts/inode.c | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -160,21 +160,27 @@ struct vfsmount *devpts_mntget(struct fi + path = filp->f_path; + path_get(&path); + +- /* Has the devpts filesystem already been found? */ +- if (path.mnt->mnt_sb->s_magic != DEVPTS_SUPER_MAGIC) ++ /* Walk upward while the start point is a bind mount of ++ * a single file. ++ */ ++ while (path.mnt->mnt_root == path.dentry) ++ if (follow_up(&path) == 0) ++ break; ++ ++ /* devpts_ptmx_path() finds a devpts fs or returns an error. */ ++ if ((path.mnt->mnt_sb->s_magic != DEVPTS_SUPER_MAGIC) || ++ (DEVPTS_SB(path.mnt->mnt_sb) != fsi)) + err = devpts_ptmx_path(&path); + dput(path.dentry); +- if (err) { +- mntput(path.mnt); +- return ERR_PTR(err); +- } ++ if (!err) { ++ if (DEVPTS_SB(path.mnt->mnt_sb) == fsi) ++ return path.mnt; + +- if (DEVPTS_SB(path.mnt->mnt_sb) != fsi) { +- mntput(path.mnt); +- return ERR_PTR(-ENODEV); ++ err = -ENODEV; + } + +- return path.mnt; ++ mntput(path.mnt); ++ return ERR_PTR(err); + } + + struct pts_fs_info *devpts_acquire(struct file *filp) diff --git a/queue-4.14/series b/queue-4.14/series index e72d8bc2f06..da803db4650 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -19,3 +19,5 @@ usb-yurex-fix-out-of-bounds-uaccess-in-read-handler.patch usb-serial-mos7840-fix-status-register-error-handling.patch usb-quirks-add-delay-quirks-for-corsair-strafe.patch xhci-xhci-mem-off-by-one-in-xhci_stream_id_to_ring.patch +devpts-hoist-out-check-for-devpts_super_magic.patch +devpts-resolve-devpts-bind-mounts.patch