April 18, 2012
Building a chroot Jail for an Arbitrary Program
I recently had to build a chroot jail in order to run an executable I didn’t write in a secure enviorment. As this isn’t something there are many tutorials for, I thought it might be benificial to write one. Note that properly securing the jail is beyond the scope of this article and is better covered elsewhere. Instead this will cover how build a chroot environment with the dependencies your program needs to run.
So without further ado, let’s build a chroot environment. For this example we’ll secure /bin/date
. So let’s create a chroot directory and copy the executable in.
mkdir ~/chroot
mkdir ~/chroot/bin
cp /bin/date ~/chroot/bin
Step 1: Finding the needed shared libraries.
Well, that was easy enough, let’s go ahead and try to chroot. Note that only root can chroot
, so you will need to use sudo
or su
, whichever is appropriate for your setup.
$ sudo chroot ~/chroot/ /bin/date
chroot: failed to run command ‘/bin/date’: No such file or directory
This error might make you think that /bin/date
is missing, but that’s not the case. What is actually happening is the system is unable to locate the shared libraries required. Lets figure out what those are.
$ ldd ~/chroot/bin/date
linux-vdso.so.1 => (0x00007fff074ca000)
librt.so.1 => /lib/librt.so.1 (0x00007f6eaeb4c000)
libc.so.6 => /lib/libc.so.6 (0x00007f6eae7ab000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007f6eae58f000)
/lib/ld-linux-x86-64.so.2 (0x00007f6eaed54000)
Ok, so what we have here is a list of the shared libraries date
is using and their location on disk. So we can simply copy them into the proper place in our chroot.
$ mkdir ~/chroot/lib
$ cp /lib/librt.so.1 ~/chroot/lib/
$ cp /lib/libc.so.6 ~/chroot/lib/
$ cp /lib/libpthread.so.0 ~/chroot/lib/
$ cp /lib/ld-linux-x86-64.so.2 ~/chroot/lib/
Notice linux-vdso.so.1
does not have a file associated with it. That’s because this is a special shared library provided by the kernel.
Now try running inside your chroot jail again:
$ sudo chroot ~/chroot /bin/date
Thu Apr 19 02:51:12 UTC 2012
Ok that looks pretty good, but compare that to running outside the chroot
$ ~/chroot/bin/date
Wed Apr 18 22:52:01 EDT 2012
Notice that the timezone is wrong when run inside the chroot. Let’s see if we can figure out why in step 2:
Step 2: Finding needed files
There is no sure way to find all the files that your process is going to need, but most of the time you can take a pretty good guess as to most of them. For example if you’re chrooting Python, you probably need all those files from a standard Python install. For those that aren’t obvious, there is one tool that can help you. strace
lets you capture all the system calls that a process is making. The -e option lets you watch for a specific call. So let’s try it on our date
program.
$ strace -e open ~/chroot/bin/date
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib/librt.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 3
Ok, so the first few are attempting to dynamically load some libraries, which may sometimes be important for your process, but in this case we can get away without them. The last one however is important. So let’s add /etc/localtime
to our chroot directory.
$ mkdir ~/chroot/etc
$ cp /etc/localtime ~/chroot/etc/
$ sudo chroot ~/chroot /bin/date
Wed Apr 18 23:00:47 EDT 2012
Bingo! Correct time and timezone. Hopefully this will help anyone having trouble getting programs to run inside a chroot jail. If you have any questions or comments, feel free to reach out to me on Twitter or GitHub.