Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a unix installation that's supposed to be usable both as a chroot and as a standalone system. If it's running as a chroot, I don't want to run any service (cron, inetd, and so on), because they would conflict with the host system or be redundant.

How do I write a shell script that behaves differently depending on whether it's running in a chroot? My immediate need is a modern Linux system, with /proc mounted in the chroot, and the script is running as root, but more portable answers are welcome as well.

More generally, suggestions that work for other containment methods would be interesting. The practical question is, is this system supposed to be running any services? (The answer being no in a chroot, and yes in a full-fledged virtual machines; I don't know about intermediate cases such as jails or containers.)

share|improve this question
2  
Duplicate of stackoverflow.com/questions/75182/… –  l0b0 Nov 9 '11 at 8:21
add comment

2 Answers

up vote 14 down vote accepted

What I've done here is to test whether the root of the init process (PID 1) is the same as the root of the current process. Although /proc/1/root is always a link to / (unless init itself is chrooted, but that's not a case I care about), following it leads to the “master” root directory. This technique is used in a few maintenance scripts in Debian, for example to skip starting udev after installation in a chroot.

if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
  echo "We are chrooted!"
else
  echo "Business as usual"
fi

(By the way, this is yet another example of why chroot is useless for security if the chrooted process has root access. Non-root processes can't read /proc/1/root, but they can follow /proc/1234/root if there is a running process with PID 1234 running as the same user.)

If you do not have root permissions, you can look at /proc/1/mountinfo and /proc/$$/mountinfo (briefly documented in filesystems/proc.txt in the Linux kernel documentation). This file is world-readable and contains a lot of information about each mount point in the process's view of the filesystem. The paths in that file are restricted by the chroot affecting the reader process, if any. If the process reading /proc/1/mountinfo is chrooted into a filesystem that's different from the global root (assuming pid 1's root is the global root), then no entry for / appears in /proc/1/mountinfo. If the process reading /proc/1/mountinfo is chrooted to a directory on the global root filesystem, then an entry for / appears in /proc/1/mountinfo, but with a different mount id. Incidentally, the root field ($4) indicates where the chroot is in its master filesystem.

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]
share|improve this answer
add comment

As mentioned in Portable way to find inode number and Detecting a chroot jail from within, you can check whether the inode number of / is 2:

$ ls -di /
2 /

An inode number that's different from 2 indicates that the apparent root is not the actual root of a filesystem. This will not detect chroots that happen to be rooted on a mount point.

share|improve this answer
    
On what filesystems does this heuristic work? –  Gilles Nov 9 '11 at 11:36
    
Tested on ext3 and hfs. –  l0b0 Nov 9 '11 at 11:52
    
So I was fooling around, and I think I've found a more reliable method that doesn't require root permissions (Linux only). I'm still open to counter-examples or more portable methods. –  Gilles Nov 9 '11 at 19:15
1  
This is true for ext[234], but not of all filesystems. It also only tests that your root is the root of the filesystem, which may not be mounted as the real root. In other words, if you mount another partition in /jail and chroot /jail, then it will look like the real root to this test. –  psusi Nov 9 '11 at 19:26
    
@Gilles I just wanted to bring your attention to psusi's point (since you were not notified) - the inode number of each separate, "real" filesystem will be 2. (Exceptions include, for instance, tmpfs. I haven't investigated much further.) –  rozcietrzewiacz May 29 '12 at 13:14
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.