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)" ]
This is a pure Linux solution. It may be generalizable to other Unix variants with a sufficiently similar /proc (Solaris has a similar /proc/1/root, I think, but not mountinfo).
init(8)would absolutely need to have the #1 slot unless there's some kind of hard-coded nature that requires it (in which I'd still be unsure as to why). Of course, the BSDs have much more advanced jails than just chroot, so I'm not even sure how problematic this is. – Adam Katz Jan 16 '15 at 10:02/proc. My answer wasn't meant to address anything but Linux anyway. – Gilles 'SO- stop being evil' Jan 16 '15 at 11:40sudofor perm on my system, here is your idea in an alias:alias ischroot='[ "$(sudo stat -c %d:%i /)" != "$(sudo stat -c %d:%i /proc/1/root/)" ] && echo "Yes, we are chrooted!" || echo "No chroot detected."'– Adam D. Jan 14 '16 at 02:49psandgrepto find the init pid. – Adam D. Jan 14 '16 at 03:02mountinfofor both PID##and1. Why? – sbhatla Jun 10 '17 at 04:12mountinfofile isn't a good test for the process being chrooted. But if the information differs for process 1 and for the running process, that shows that the running process is running in a different root from process 1. – Gilles 'SO- stop being evil' Jun 10 '17 at 19:17/procmounted is not a security flaw, because chroot alone is not a security mechanism. You can get security from chroot only if the processes running in the chroot run with separate user IDs from processes running outside the chroot. Otherwise chroot does not protect you, for example, from a process that kills or ptraces another process that's running outside the chroot. In that case/proc/$pid/rootdoes not permit bypassing the chroot. – Gilles 'SO- stop being evil' Jan 11 '18 at 19:00[/testwith a simpleawkcommand:if stat -c %d:%i / /proc/1/root/. | awk -v RS= '{ exit $1 != $2; }'; then(setting record separator to empty string automatically makes newline a field separator). Even easier if yourtesthas the-ef(same file) comparison! – Toby Speight Mar 14 '19 at 13:52