Yet another how to chroot a user guide

There are loads of "how to set up chroot" guides out there, and this is yet another one as I had to piece together quite a few to get things to work they way I needed them to and to my liking. So as I need to make notes for when I inevitably need to set this up again I figure I may as well share those notes. Hopefully this well be a suitably idiot guide. This is written for a Ubuntu system so on other systems your mileage may vary.

The basics

I'm going to break this down to the first steps that are vital for getting any chroot jail to work and then look at making it useful. But even these basic steps could probably be made even more minimal if you really wanted to.

For the purpose of these notes just assume that every command is either done as root or prefixed with sudo also that unless explicitly stated that the chroot directory is the working directory.

Create the basic directories

First create the directory that will be the root of your chroot jail:
mkdir /home/chroot
Within that directory create directories for dev etc bin and tmp and also vitally
lib/x86_64-linux-gnu
mkdir -p dev etc tmp lib/x86_64-linux-gnu
That's the basic structure that's needed to do pretty much anything, other directories will be created later as needed.

Having created our basic directory structure we can start to populate it with the files we just can't live with out. The idea here is to create as little as possible as the less there is in the jail the less there is to abuse.

Populate $chroot/dev

Next up populate dev change into your newly created dev directory and :

You quite possibly don't need all of those, but null , random and urandom are almsot certainly required.

The final vital files

Now to add a few things to our new etc directory, as ever depending on what you want to do with your chroot jail you may not need this much - add only the bare minimum you need.

One further file has to be copied into our chroot jail before you can even think about testing things. The file libnss_files.so.2 is required to look verify the chrooted user in the minimal /etc/passwd file.
cp /lib/x86_64-linux-gnu/libnss_files.so.2 /home/chroot/lib/x86_64-linux-gnu/ libnss_files.so.2
Now that's in place we can test the chroot environment:
chroot --userspec=user /home/chroot/
chroot: failed to run command /bin/bash : No such file or directory

Predictably things didn't work, as we have no executables that can be run in the chroot jail. What executables and other files you need to add depend very much on what you want to do. I was creating a minimalist user environment so that will be my example.

Making it useful

Populating $chroot/etc

First a few more things in etc :

Create a profile of some sort in etc to reflect what you want to do, at the very least you want to set the path. Depending on how restricted your environment and how much hassle you can live with - you could make this a non-standard path to obscure things a bit and make it harder for peopel to guess at things. However due to the assumptions that many many programs make you'll almost certianly need a /bin directory containing sh . For the puposes of this example I'm going to assume almost everything gets dumped in bin .

This is where you need to determien what the minimum set of commands are that you want to make available. You also want to make sure there's nothing that is too handy for breaking out of the jail, so really avoid anything setuid or setgid.

For my particular needs I want to mainly use ksh and a few other utilities so I copied the following into bin

I actually have a few more bits installed but those will do by way of example.

Given the problems that arise from a lack of /bin/sh I created a symlink from ksh to sh and to provide a restricted shell also to rksh

Now as I didn't recompile all of those as static binaries they won't work without also copying across the relevant libraries so time to run ldd against each one and see what's needed.
e.g.
ldd ksh
linux-vdso.so.1 => (0x00007fff1dbfe000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9658885000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965857f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f96581b8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9658a92000)

So I can now copy the refernced libraries into the same place within my chroot jail
cp /lib/x86_64-linux-gnu/libdl.so.2 /home/chroot/lib/x86_64-linux-gnu/libdl.so.2
Copy in each library, and then run ldd on the next program and repeat. There are scripts out there that makes this easier, but it's good to understand how it actually works.

Final steps

That's pretty much it, depending on what the purpose of your chroot is and who'll be using it. In my case I need it for what has to be considered a hostile environment (the Internet), so I want to tighten things up a bit further.

To make life a bit better I created a home directory for the chrooted user, but then change the ownership and remove all write permissions. All the profile and rc files were created outside of the home directory and symlinks created for them. Every file and directory which didn't need to be writable was made read only (so everything but tmp and dev )

With all that done I added the chroot option to my SSHD config and let people in.
ChrootDirectory /home/chroot
That is of course all well and good if you're using SSH, if you're using something else such as telnetd that relies on say /etc/pam.d/login then you'll need to configure pam_chroot . Thankfully this is also surprisingly easy. Just edit the relevant PAM configuration file (let's assume login ) to add the line:
session required pam_chroot.so
in the relevant place. Then create or edit the file /etc/security/chroot.conf to add the user to be chrooted and where their jail is. The JailKit page goes into more details about this.

Futher gotchas

Given that package managers are all the rage these days and often safer than compiling your own. If you want to download and install a package in chroot without breaking your main system. Say maybe a lighter mail server. Then you'll want to follow these instructions:

Acknowledgements

I looked at far too many pages trying to work out how to set up just the chrooted environment that I neeeded. However the following were particualrly useful: