#685034 debianutils: ischroot fails to detect if it is running in a chroot

Package:
debianutils
Source:
debianutils
Description:
Miscellaneous utilities specific to Debian
Submitter:
Bob Proulx
Date:
2013-08-26 18:51:04 UTC
Severity:
normal
#685034#5
Date:
2012-08-15 23:51:43 UTC
From:
To:
When I create a chroot the ischroot command fails to detect it and
returns an error code.  It is good to return an error but since the
purpose of ischroot is to detect if it is running in a chroot the
result is not useful.

To recreate the problem I recommend a throwaway VM instance because
the result is a slightly broken system due to an initscripts bug.

* Create a Squeeze chroot.

  # mkdir /srv/chroot
  # cd /srv/chroot
  # debootstrap squeeze squeeze-test http://ftp.us.debian.org/debian

* Configure policy-rc.d to avoid starting any daemons in the chroot.

  # cd squeeze-test
  # printf '#!/bin/sh\nexit 101\n' > ./usr/sbin/policy-rc.d
  # chmod a+x ./usr/sbin/policy-rc.d

* Ensure that it is up to date.

  # chroot $PWD su -
  # apt-get update
  # apt-get upgrade

* Upgrade it to Wheezy.

  # sed --in-place s/squeeze/wheezy/g /etc/apt/sources.list
  # apt-get update
  # apt-get upgrade
  # apt-get dist-upgrade

At this point the system has two problems.  One of them is that
'ischroot' cannot determine that it is in a chroot.

  # ischroot ; echo $?
  2

As to how to fix this I have no good ideas.  I did not look at the
ischroot source and do not know what method it uses.  I am only
chasing this due to the problem with the initscripts process for /run
migration and this is the earliest problem that I found.  (Hint to
others: To avoid the initscripts problem replace ischroot with
/bin/true between the upgrade and dist-upgrade steps.)

I can only think of using the inode of the root filesystem for
detection.

In the chroot:

  # ls -ldogi /
  126483 drwxr-xr-x 22 4096 Aug 15 23:30 /
  ^^^^^^-- inode number is not 2

On the host system outside any chroot:

  # ls -ldogi /
  2 drwxr-xr-x 21 4096 Aug 15 07:02 /
  ^-- inode number is usually 2

Outside the chroot the inode of the root filesystem is usually 2 for
traditional Unix filesystems and for ext2, ext3, ext4.  But I do not
know about others.

Thanks,
Bob

#685034#10
Date:
2013-08-26 10:02:10 UTC
From:
To:
I think the root issue (if you allow me the pun) is that you didn't
mount /proc in your chroot.

From the source code:

/* On Linux we can detect chroots by checking if the
 * devicenumber/inode pair of / are the same as that of
 * /sbin/init's. This may fail if not running as root or if
 * /proc is not mounted, in which case 2 is returned.
 *
 * If /proc/1/root exists but can not be stated as root,
 * we're running in some limited environment (eg. vserver),
 * which we consider as chroot here.
 */

And the root of /sbin/init is checked via stat -L /proc/1/root


The man page should mention this requirement though.

#685034#13
Date:
2013-08-26 18:49:19 UTC
From:
To:
Emmanuel Kasper wrote:

There is no requirement to mount /proc or /sys or /dev/pts anything
else in a chroot.  Having /proc mounted does not make it a chroot.  It
is a chroot without too.

Also when dealing with a large number of dynamically managed chroots
it is a burden to also need to mount an unspecified collection of
things like /proc too.  This has never been required previously.  I
think it is unreasonable for ischroot to create this requirement.

I applaud ischroot for returning an error exit code in the case that
it cannot make a determination.  That was the right thing to do.

The real problem is that since this utility appeared other packages
have started to use it.  Unfortunately some have used it incorrectly.
The sysvinit package started the problem but has since been fixed.
This caused me problems during Squeeze->Wheezy upgrades in chroots.  I
see that at this moment libc6 is still buggy.

    if ischroot 2>/dev/null; then

That does not take into consideration exit code 2.

Additionally I will facetiously joke that the program should be
renamed to ischroot_and_proc too.

But if ischroot can actually make the correct determination then I
think that is better.  The program is heuristic based.  (Meaning that
it just makes some guesses based upon programed rules.)  I think that
if /proc is not mounted such that its primary criteria is unavailable
that it should fall back to checking if "/" is inode 2.  If so then I
think it can safely guess that it is in a chroot.  This is still not
100% for all cases.  Someone might make an lvm volume for each chroot
in which case "/" would still be inode 2.  But it would be one large
step closer than it is now.

If I can squeeze some time I will try to prepare a patch.  Thank you
for generating activity in this bug and bringing it back to my
attention.

Bob