Package: schroot
Version: 1.6.10-3
Severity: normal
Tags: upstream

As documented in
<http://lxr.free-electrons.com/source/Documentation/filesystems/devpts.txt?v=3.16>
and in <https://www.kernel.org/doc/Documentation/filesystems/devpts.txt>
(for historical context you might want to read the v3.16 version, chosen to
represent Debian jessie, before the latest version), the preferred way to
set up /dev/pts inside containers in recent kernels is to mount a new
instance of the devpts filesystem on /dev/pts, either use ptmxmode=666 or
chmod /dev/pts/ptmx to 0666 afterwards, and arrange for /dev/ptmx to be
equivalent to /dev/pts/ptmx via a symbolic link or bind-mount.

In particular, this would make the chroots created by debootstrap
versions 1.0.76 to 1.0.88 (inclusive) work as expected. In those chroots,
/dev/ptmx is a symbolic link to pts/ptmx. That is considered to be a RC
bug in debootstrap (#817236, RC because it broke existing functionality),
and I have proposed a patch; but with my proposed patch, debootstrap
will still create chroots with /dev/ptmx -> pts/ptmx if it is run
in a container manager that restricts device node creation, such as
systemd-nspawn, because that seemed better than failing outright.

Invoking script(1) is a common way to test this.

A nice side-effect of this change, which I discovered while testing a
cut-down version of the same code in a new debootstrap autopkgtest, is
that it makes script(1) work inside "schroot --sbuild" inside a LXC
container on a Debian jessie kernel. Previously, that would have failed.

I'm filing this as a new bug rather than detaching one of the merged bugs
from #817236 because the only one that originally concerned schroot
was #817236 itself, and it would seem needlessly confusing to repurpose
that bug number.

I attach a schroot patch that does as I request. I'm also going to attach
a patch to #817236 that will extend debootstrap's autopkgtest to run a
heavily cut-down version of the same logic, to confirm that it does in
fact work.

Unfortunately, this does cause a regression for interactive use:
processes inside an interactive schroot cannot tell that their
stdin/stdout/stderr is in fact connected to a terminal, because that
terminal is not visible to them. As a result, programs like sudo and
screen will refuse to run, unless wrapped in something like
"script /dev/null". So it might be necessary for schroot to provide
its own pty (one that *is* valid inside the chroot) and forward
input/output to/from the terminal outside the chroot, or something?
(I think that's what container managers like lxc and systemd-nspawn do.)
As a result I'm not tagging this as 'patch'.

Regards,
    S
From: Simon McVittie <s...@debian.org>
Date: Mon, 20 Feb 2017 10:43:24 +0000
Subject: Mount a new instance of /dev/pts in the chroot

This is considered to be best-practice for container managers in
Linux >= v2.6.29 with CONFIG_DEVPTS_MULTIPLE_INSTANCES=y. That config
option was made unconditional in v4.7.

This has some assumptions, which cannot be avoided if we are going to
mount /dev/pts using schroot's fstab:

* If the kernel is older than v4.7, it is assumed to be v2.6.29 or
  later with CONFIG_DEVPTS_MULTIPLE_INSTANCES=y. Users of older kernels,
  or intermediate versions with CONFIG_DEVPTS_MULTIPLE_INSTANCES=n,
  can revert this change via /etc.

* gid 5 must be the right owner for ptys. This is correct for Debian
  (it's the hard-coded tty group specified in base-passwd) and probably
  many other distributions (it's systemd's configure-time default) but
  not necessarily correct everywhere. However, if the host system and the
  chroot disagree on the right gid, schroot's previous behaviour would
  have been wrong anyway, because it bind-mounted the host's /dev/pts.

* /dev/ptmx inside the chroot must be either a real device node (as
  created by debootstrap < 1.0.76) or a symlink to pts/ptmx
  (as created by debootstrap >= 1.0.76).

I have proposed a debootstrap patch to make it create the real device
node again if possible. However, there is a desire for debootstrap
to be runnable under container managers that restrict creation of
device nodes, such as systemd-nspawn; under these container managers,
creating /dev/ptmx as a symlink to pts/ptmx is the best that can be
done.

Bind-mounting /dev/pts/ptmx over /dev/ptmx, so that we get the
new instance's /dev/ptmx equivalent instead of the host's, can only
be done from code, so I have done it in the 10mount hook instead of
in the fstab.
---
 etc/profile-templates/buildd/linux/fstab  |  2 +-
 etc/profile-templates/default/linux/fstab |  2 +-
 etc/profile-templates/desktop/linux/fstab |  2 +-
 etc/profile-templates/sbuild/linux/fstab  |  2 +-
 etc/setup.d/10mount                       | 12 ++++++++++++
 5 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/etc/profile-templates/buildd/linux/fstab b/etc/profile-templates/buildd/linux/fstab
index 26efe88..f2f6136 100644
--- a/etc/profile-templates/buildd/linux/fstab
+++ b/etc/profile-templates/buildd/linux/fstab
@@ -1,4 +1,4 @@
-/dev/pts        /dev/pts        none    rw,bind         0       0
+/dev/pts        /dev/pts        devpts  rw,newinstance,ptmxmode=666,mode=620,gid=5 0 0
 tmpfs           /dev/shm        tmpfs   defaults        0       0
 # Mount a large scratch space for the build, so we don't use up
 # space on an LVM snapshot of the chroot itself.
diff --git a/etc/profile-templates/default/linux/fstab b/etc/profile-templates/default/linux/fstab
index 777f0ed..181ed80 100644
--- a/etc/profile-templates/default/linux/fstab
+++ b/etc/profile-templates/default/linux/fstab
@@ -1,5 +1,5 @@
 /dev            /dev            none    rw,bind         0       0
-/dev/pts        /dev/pts        none    rw,bind         0       0
+/dev/pts        /dev/pts        devpts  rw,newinstance,ptmxmode=666,mode=620,gid=5 0 0
 /home           /home           none    rw,bind         0       0
 /tmp            /tmp            none    rw,bind         0       0
 
diff --git a/etc/profile-templates/desktop/linux/fstab b/etc/profile-templates/desktop/linux/fstab
index 7f61d8d..b0dae37 100644
--- a/etc/profile-templates/desktop/linux/fstab
+++ b/etc/profile-templates/desktop/linux/fstab
@@ -1,5 +1,5 @@
 /dev            /dev            none    rw,bind         0       0
-/dev/pts        /dev/pts        none    rw,bind         0       0
+/dev/pts        /dev/pts        devpts  rw,newinstance,ptmxmode=666,mode=620,gid=5 0 0
 /home           /home           none    rw,bind         0       0
 /tmp            /tmp            none    rw,bind         0       0
 
diff --git a/etc/profile-templates/sbuild/linux/fstab b/etc/profile-templates/sbuild/linux/fstab
index 26efe88..f2f6136 100644
--- a/etc/profile-templates/sbuild/linux/fstab
+++ b/etc/profile-templates/sbuild/linux/fstab
@@ -1,4 +1,4 @@
-/dev/pts        /dev/pts        none    rw,bind         0       0
+/dev/pts        /dev/pts        devpts  rw,newinstance,ptmxmode=666,mode=620,gid=5 0 0
 tmpfs           /dev/shm        tmpfs   defaults        0       0
 # Mount a large scratch space for the build, so we don't use up
 # space on an LVM snapshot of the chroot itself.
diff --git a/etc/setup.d/10mount b/etc/setup.d/10mount
index 296a162..8382151 100755
--- a/etc/setup.d/10mount
+++ b/etc/setup.d/10mount
@@ -269,3 +269,15 @@ if [ $STAGE = "setup-start" ] || [ $STAGE = "setup-recover" ]; then
     fi
 
 fi
+
+if [ $STAGE = "setup-start" ] || [ $STAGE = "setup-recover" ]; then
+    # Depending on how /dev was set up, /dev/ptmx might either be
+    # character device (5,2), or a symbolic link to pts/ptmx.
+    # Either way we want it to be equivalent to /dev/pts/ptmx, assuming
+    # both exist.
+    if [ -e "$CHROOT_PATH/dev/pts/ptmx" ] && \
+            [ -e "$CHROOT_PATH/dev/ptmx" ] && \
+            ! [ "$CHROOT_PATH/dev/pts/ptmx" -ef "$CHROOT_PATH/dev/ptmx" ]; then
+        mount --bind "$CHROOT_PATH/dev/pts/ptmx" "$CHROOT_PATH/dev/ptmx"
+    fi
+fi

Reply via email to