** Changed in: linux (Ubuntu Bionic)
       Status: Triaged => Fix Committed

-- 
You received this bug notification because you are a member of Kernel
Packages, which is subscribed to linux in Ubuntu.
https://bugs.launchpad.net/bugs/1755857

Title:
  devpts: handle bind-mounts

Status in linux package in Ubuntu:
  Fix Committed
Status in linux source package in Bionic:
  Fix Committed

Bug description:
  Hey everyone,

  I sent a few patches to fix a regression caused by wrong behavior in
  the devpts filesystem when used with the TIOCGPTPEER ioctl() we
  implemented a while back. The context and reproducer can be taken from
  my following commit message. The required patches are in Greg's tree
  and are:

  1. 
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/commit/?h=tty-testing&id=7d71109df186d630a41280670c8d71d0cf9b0da9
  2. 
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/commit/?h=tty-testing&id=a319b01d9095da6f6c54bd20c1f1300762506255
  3. 
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/commit/?h=tty-testing&id=4e15f760a43c7cb88e2b7ad6882501ccab5de29f
  4. 
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/commit/?h=tty-testing&id=ce290a19609d5ecd4a240a4750e0ed9a476cf015

  devpts: resolve devpts bind-mounts
  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.

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1755857/+subscriptions

-- 
Mailing list: https://launchpad.net/~kernel-packages
Post to     : kernel-packages@lists.launchpad.net
Unsubscribe : https://launchpad.net/~kernel-packages
More help   : https://help.launchpad.net/ListHelp

Reply via email to