]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Jul 2018 13:24:09 +0000 (15:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Jul 2018 13:24:09 +0000 (15:24 +0200)
added patches:
devpts-hoist-out-check-for-devpts_super_magic.patch
devpts-resolve-devpts-bind-mounts.patch

queue-4.14/devpts-hoist-out-check-for-devpts_super_magic.patch [new file with mode: 0644]
queue-4.14/devpts-resolve-devpts-bind-mounts.patch [new file with mode: 0644]
queue-4.14/series

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 (file)
index 0000000..6a952f9
--- /dev/null
@@ -0,0 +1,88 @@
+From 7d71109df186d630a41280670c8d71d0cf9b0da9 Mon Sep 17 00:00:00 2001
+From: Christian Brauner <christian.brauner@ubuntu.com>
+Date: Tue, 13 Mar 2018 17:55:24 +0100
+Subject: devpts: hoist out check for DEVPTS_SUPER_MAGIC
+
+From: Christian Brauner <christian.brauner@ubuntu.com>
+
+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 <christian.brauner@ubuntu.com>
+Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..8fea6fe
--- /dev/null
@@ -0,0 +1,148 @@
+From a319b01d9095da6f6c54bd20c1f1300762506255 Mon Sep 17 00:00:00 2001
+From: Christian Brauner <christian.brauner@ubuntu.com>
+Date: Tue, 13 Mar 2018 17:55:25 +0100
+Subject: devpts: resolve devpts bind-mounts
+
+From: Christian Brauner <christian.brauner@ubuntu.com>
+
+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/<pid>/fd/<nr>
+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 <christian.brauner@ubuntu.com>
+Suggested-by: Eric Biederman <ebiederm@xmission.com>
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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)
index e72d8bc2f066846336b2128ff1b40b4c292bc130..da803db4650f74a4ac0fd766a9a83312a1e10ee0 100644 (file)
@@ -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