Powered by SmartDoc

Setting up a chroot jail for rssh

Derek Martin
This document is intended to provide some hints for setting up a chroot jail for rssh v2.1 and later.


This document is intended to provide some hints for setting up a chroot jail for rssh v2.1 and later. It is virtually impossible to provide exact instructions for this, due to differences in things like the libraries on different systems, whether or not the binaries are statically linked, etc.

IMPORTANT NOTE ABOUT wordexp() IMPLEMENTATIONS: rssh requires a working implementation of the wordexp() library function, specified by POSIX.2 (or whatever they're calling it these days). A number of vendors ship a version of wordexp() that execvp()'s the system shell in order to expand the arguments. This means that if you are using such a platform, you'll need to copy their system shell into the chroot jail, along with all the other necessary files. The symptoms of this problem are:

  1. When a user logs in, they immediately get Connection closed.
  2. In the system logs, rssh reports error expanding arguments for user ...

For Solaris 9, the required shell is /bin/ksh. For AIX 5.2, you need /usr/bin/ksh93. FreeBSD also has this problem, but I don't know what the default system shell is on FreeBSD. Other platforms will probably also experience this problem. If you need help determining which shell to include, try running rssh with strace or truss, whichever your system has. See the relevant manpages for details.

NOTE: There is now a shell script provided with rssh which should create working chroot jails, at least on Red Hat linux systems, and probably on most derivatives of Red Hat (like Fedora, etc.). It will probably also work with other Linux distributions, and may work on other platforms, with some minor modifications.

N.B.: if you are not installing from the official Red Hat RPM provided on the Sourceforge page, you may need to edit the script to modify some of the paths before it will work for you. This includes cases where you are installing from source. The script expects to find rssh_chroot_helper in /usr/libexec, but installing from source may leave it elsewhere, depending on what options you gave to the ./configure script.

Even if you plan to use the script, please read the rest of this document so that you understand what it is doing, in case things go wrong. To run the script, you just need to give it the directory you want to use as your chroot jail:

<path to script>/mkchroot.sh /my/chroot/jail

There are a few other options, which will not be needed by most users. For details, have a look at the shell script. It's pretty well commented, and should be self-explanatory.

Setting up the jail manually

The important things to note about building a chroot jail is that you must duplicate parts of the root filesystem: those parts containing the libraries needed for whatever binaries you will be using, the configuration files for those binaries, /etc/passwd, and possibly other things. So if your chroot jail is /usr/chroot, you'll need to copy those items into the same locations relative to /usr/chroot. For example, you will need to copy /etc/passwd to /usr/chroot/etc/passwd.

You will also need to copy the binaries for rssh_chroot_helper, scp, and sftp-server into your chroot jail, in the same locations as they were configured by rssh, but relative to the chroot jail. For example, by default on Red Hat systems (my development platform), the binaries you need to use rssh are usually installed in the following locations:

(assuming you did not specify a --prefix when you configured rssh).

Presumably, rssh detected the scp and sftp-server binaries in those locations, and will be looking for them in those locations, RELATIVE TO THE ROOT OF THE CHROOT JAIL. So you will need to copy these files into the chroot jail:

# cp /usr/bin/scp /usr/chroot/usr/bin/scp
# cp /usr/libexec/openssh/sftp-server \
# cp /usr/local/bin/rssh_chroot_helper \

[Before you copy the files, you obviously need to create the directory structure to copy them into.]

Next, you will need copies of the libraries these programs are linked against. This can be difficult to determine on some systems, which may require the use of the ldd program, and/or the use of strace or truss. On Red Hat systems, ldd shows that the following libraries are needed for scp:

$ ldd `which scp`
      libresolv.so.2 => /lib/libresolv.so.2 (0x40029000)
      libutil.so.1 => /lib/libutil.so.1 (0x4003c000)
      libz.so.1 => /usr/lib/libz.so.1 (0x4003f000)
      libnsl.so.1 => /lib/libnsl.so.1 (0x4004d000)
      libcrypto.so.2 => /lib/libcrypto.so.2 (0x40062000)
      libkrb5.so.3 => /usr/kerberos/lib/libkrb5.so.3 (0x40136000)
libk5crypto.so.3 => /usr/kerberos/lib/libk5crypto.so.3 \
libcom_err.so.3 => /usr/kerberos/lib/libcom_err.so.3 (0x401a4000)
      libc.so.6 => /lib/i686/libc.so.6 (0x42000000)
      libdl.so.2 => /lib/libdl.so.2 (0x401a6000)
      /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

You need to copy each of these in turn into the chroot jail, or else rssh will not be able to execv() the binary. The error message logged will likely be something to the effect of no such file or directory, in such a case. Following our example above, you would use the following commands:

# cp /lib/libresolv.so.2 /usr/chroot/lib/libresolv.so.2
# cp /lib/libutil.so.1 /usr/chroot/lib/libutil.so.1
# cp /usr/lib/libz.so.1 /usr/chroot/usr/lib/libz.so.1

You need to make sure that you do this for sftp-server as well, in case the libraries required are different. If rssh is linked statically, you should not need to worry about what libraries it is linked against. Otherwise, it may be required.

Note that the last two libraries in this example are used by the dynamic linker. If any of the binaries in question are linked dynamically (and in most cases, this will be true), you need to also copy any configuration files for the dynamic linker into your chroot jail. On Linux, you want the files /etc/ld.so* to be copied.

Config files

You should not need to copy the config file for rssh, since it will already be done executing before the call to chroot(). You will likely need to copy /etc/passwd, so that the system can identify the user using the program. Some programs may fail if the user can not be identified. In my testing, scp errored out if the username could not be determined. If you need to copy the password file, the following will suffice.

# cp /etc/passwd /usr/chroot/etc/passwd

You probably will also need to copy the files related to the dynamic linker, for example on Red Hat Linux:

# cp /etc/ld.so* /usr/chroot/etc/

Authentication concerns

You may need to copy additional libraries, if your system depends upon them for authentication. For example, in my testing, I needed to copy /lib/libnss_files.so.? into the chroot jail. Without it, the scp command failed, complaining that my user ID was an unknown user. If you use LDAP authentication on the server, you will probably need to also copy libnss_ldap.so.? into your chroot jail.


On most systems, the syslog() library function works by writing messages into a FIFO, such as for example /dev/log. Once the chroot() system call is executed, the program will no longer have access to /dev/log. Many systems have a syslogd that will allow you to specify additional FIFOs which syslogd will listen to. On Linux systems, this is generally done with the -a option to syslogd. In order for logging to continue to work properly once inside the chroot jail, you will need to modify your start-up scripts to start syslog with an additional FIFO inside the jail, something like this:

/sbin/syslogd -a /usr/chroot/dev/log

You will need to make sure the directory /usr/chroot/dev exists.

User details

You probably want to have a home area inside the chroot jail, with home directories for users inside the chroot. The /etc/passwd file should contain the full path to the user's home directories. For example, if the user's home directory is /usr/chroot/home/joe, then that is the directory that should be specified in /etc/passwd. The directory specified in the copy of the passwd file inside the chroot jail is not ever used, so it does not matter if you change it to the path relative to the root of the chroot jail (i.e. /home/joe, in this case).

When it executes, the chroot helper will determine if the user's home directory is contained within the chroot jail, and automatically put the user in it if it is. If it is not, the helper program will leave the user in the root of the chroot jail. You should take care to make sure that you are getting the behavior that you want before putting a chrooted rssh into production.

In the next minor release of rssh (v2.1), you will be able to specify the location of different chroot jails for different users, whether or not to chroot individual users, etc. Since so many people have been asking for chroot support in rssh, I wanted to at least get something out with preliminary support. It may not currently meet everyone's needs, but it's better than nothing...

Individual jails for different users

In v2.1, you are now able to specify the location of different chroot jails for different users, whether or not to chroot individual users, etc. You might be tempted to create individual jails for each different user, and you can do that, BUT... It's probably a bad idea.

There are several reasons for this. First, it uses lots of disk space, because you need to copy the libraries and such into each one (though in some circumstances, you might be able to get away with creating hard links and/or symbolic links -- maybe). Another reason is that in order to log chroot activity, you need to create a socket for syslog to log to (i.e. /dev/log, see above) in each of the chroot jails. However, the number of sockets syslog can listen to is generally limited. On most Linux systems, that limit is a maximum of 20, though it can be changed by editing the source code to syslogd. So if you go with individual chroot jails, you either need to be satisfied without logging for most of your users, or recompile syslogd and manually configure it to open a socket in each of your users' jails. And while I haven't done it, I suspect creating large numbers of sockets for syslogd to listen to will make logging to syslog somewhat painful.

My recommendation is, if you really really really need individual chroot jails, use them. But if you can, configure a single jail where the majority of your users will live, but control their access carefully via file permissions. Only provide separate jails for very sensitive or troublesome users (or in the latter case, just disable their account and be done with it... =8^)


Setting up a proper chroot jail can be difficult, and it is always a very environment-specific operation. Because of this, I can not and will not provide any sort of support for setting up chroot jails. However, in the near future, I will make sure there is a mailing list for rssh, where you can ask questions.

If you are having problems, make sure that you have logging set up properly, if nothing else. Doing so will help you determine what kind of problems you are experiencing, as error messages will be logged to syslog.

Good luck!


rssh Home Page