THE
DEFINITIVE GUIDE TO CHROOTING CONT...
Installing the Libraries
We now have a basic environment set up and ready for an application to
run in. Next comes the most mundane, and to the beginner, most tricky
part of configuring a chroot jail. The libraries. Unless you have
compiled you application statically, which I do not recommend as it
makes updating services files a nightmare (trust me...), your
applications will be using shared libraries; they are likely configured
to read them from /lib, or /usr/lib... most applications will try
several places before failing. Generally if a library is in any
standard location, your application will find it.
Before we begin installing the libraries needed by the application
itself, we must install the NSS libraries. If you are running a service
that does not perform any user, name, or DNS lookups, you will not need
these libraries. They are, however, quite secure and pose very little
risk, especially when the passwd and shadow files are properly secured,
with only the bare necessary accounts in them. Now, for any application
that will require access to passwd, shadow, and group files, we will
install these libraries. These are the libraries that allow Linux to
look up user information, and hostname information. (When you see a
“user@hostname” prompt, Linux will first match your user id to a user
name by consulting the user database. This is done with the function
calls located in the NSS libraries.) In short, these libraries will be
used, in most cases, whether you know it or not, as they are
dynamically linked at run time. Even statically compiled applications
will require these libraries. While the exact technical details are not
important, what is important is that you copy these libraries to the
chroot jail. These libraries include, but are not limited to:
Code:
libnss_compat.so
libnss_files.so
libnss_dns.so
libnss_hesiod.so
libnss_nis.so
libnss_nisplus.so
In short, all of your nss libraries. These can be copied to the chroot
jail with the command
Code:
cp -d /usr/lib/libnss* /chroot/mysql/lib
In the case of mysql. The -d switch causes the cp command to not
resolve any symbolic links, but copy the links as they are. Now check
the symbolic links you just copied to make sure they are valid. They
may still reference the old location of the libraries before you copied
them, or they may be a relative reference which is no longer valid. If
so, delete them and replace them with valid links. More than likely,
they are already valid.
After installing the NSS libraries, we must determine which libraries
the application itself calls. This can be done with the ldd command.
Assume we have copied the mysqld command out of the mysql source tree.
To determine which shared libraries this application requires, we run
the command “ldd mysqld”. This will produce output similar to what is
below:
Code:
root@elizabeth:/usr/src/mysql-5.0.15/sql# ldd mysqld
linux-gate.so.1 => (0xffffe000)
librt.so.1 => /lib/tls/librt.so.1 (0xb7f4d000)
libz.so.1 => /usr/lib/libz.so.1 (0xb7f3a000)
libdl.so.2 => /lib/tls/libdl.so.2 (0xb7f36000)
libssl.so.0 => /usr/lib/libssl.so.0 (0xb7f05000)
libcrypto.so.0 => /usr/lib/libcrypto.so.0 (0xb7e04000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0xb7df2000)
libcrypt.so.1 => /lib/tls/libcrypt.so.1 (0xb7dc4000)
libnsl.so.1 => /lib/tls/libnsl.so.1 (0xb7dad000)
libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0xb7cf5000)
libm.so.6 => /lib/tls/libm.so.6 (0xb7cd2000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7cc9000)
libc.so.6 => /lib/tls/libc.so.6 (0xb7bad000)
/lib/ld-linux.so.2 (0xb7f5d000)
This is a listing of every shared library (aside from the NSS
libraries) which is referenced by the mysqld command, and where they
currently are on the system. These libraries must be copied from the
location specified to /chroot/[app]/lib. In most cases, applications
will search /usr/lib and /lib, among other directories, for shared
libraries before giving up. Again, if they are in nearly any standard
location such as these, most applications will find them. If not, you
can either create the directory where the application looks for these
libraries and place them there, or put symbolic links in their place.
Here again, I prefer to create a single /chroot/lib directory for all
of the shared libraries used by my chrooted services, and hard link
each individual service's libraries from there. When on library is
updated, they all are that way. For example, assume you have
apache-httpd with mod-php installed and configured with mysql support.
Now you wish to upgrade mysql. Since apache will be using
libmysqlclient.so.* from /chroot/httpd/lib, which is hard linked from
/chroot/lib, when you upgrade mysql, it will upgrade that library.
There is no need to also upgrade the library in /chroot/httpd/lib,
since it is hard linked to /chroot/lib. This solves a lot of
configuration problems which occur when you forget to roll the upgrade
out to all the chrooted services.
Installing The Device Files
Finally, we must install the necessary device files for the
application. Some applications require specific device files, such as
ssh and emacs requiring console access with /dev/console or something
similar, but in most cases, zero, null, random, andurandom will
suffice, and should be installed as a bare minimum anyway. The device
files can be created with the following commands:
Code:
mknod c 1 3 null
mknod c 1 5 zero
mknod c 1 8 random
mknod c 1 9 urandom
Should your application require any additional device files, look them
up in your system's /dev directory and use similar commands to create
them. I get the following listing when looking up the above devices:
Code:
crw-rw-rw- 1 root root 1, 3 2005-11-08 02:31 null
crw-r--r-- 1 root root 1, 8 2005-11-08 02:31 random
crw-r--r-- 1 root root 1, 9 2005-11-08 02:31 urandom
crw-rw-rw- 1 root root 1, 5 2005-11-08 02:31 zero
Where 1 is the major device number and 3,5,8, and 9 are the minor
device numbers. If we needed a console device, we would look it up in
/dev with ls -l /dev/console, getting the following output:
Code:
crw------- 1 root tty 5, 1 2005-11-08 02:32 console
We would then create the device in /chroot/[app]/dev with the following
command:
Code:
mknod c 5 1 console
Make sure the device permissions for your newly created devices match
those found in the /dev directory. In the case of /dev/console, I would
set the permissions with
Code:
chmod 600 /chroot/mysql/dev/console
This will create a basic environment in which the application is
capable of running. Most applications will also require several
configuration files to be placed in various directories as well. Bind,
for example, requires the zone files to be placed in /etc, as well as
the named.conf and rndc.conf files. Apache httpd requires httpd.conf,
and mysql requires my.cnf. Each application will have its own unique
configuration files which will need to be placed in the jail to run
properly. We must determine what these files are and place them there.
The method for each applciation will be different.
LOGGING
Once a basic user environment is installed and the applciation can run,
the next item on the agenda is to ensure that the applciation is
capable of logging to your usual logging facility, or we may not be
able to properly diagnose errors which will inevitably occur as we try
to chroot each application. I will assume that you are using the sylogd
logging dameon for your system logging, and that, at this point, syslog
itself has not been chrooted (in which case we would employ normal
syslog logging over the network). Applications will look to the
/dev/log device (actually a socket), and send logs there for eventual
logging to /var/log/syslog (or another logfile). When we start the
syslogd daemon, we can specify additional locations for this socket
anywhere we like, which will all cause logs from the relevant
application to be sent to /var/log/syslog (again, assuming you have not
chrooted syslogd). This can be specified with the -a [socket] switch.
For example,
Code:
/usr/sbin/syslogd -a /chroot/mysql/dev/log
Will not only create the usual /dev/log socket, but also an additional
socket in /chroot/mysql/dev/log, which MySQL will see as /dev/log while
running chrooted to /chroot/mysql. This will allow MySQL to send logs
to the /var/log/syslog file much like every other application using the
syslogd dameon on your system. Look through your system initialization
scripts for the line that starts syslogd and add the -a argument for
any services you are chrooting. Placing this command in individual
control scripts will not work, as each script would restart syslog,
which would delete any sockets that are already present. If we had
/chroot/httpd/dev/log, starting syslog with only the argument to put a
logging socket in /chroot/mysql/dev/log would delete the socket already
in the httpd jail. Any application which uses the syslogd logging
daemon will require these additional sockets if you wish to see the
logs it generates, which are invaluable in diagnosing problems that
will inevitable occur as you get the service chrooted. Without these
additional sockets, the logs will disappear into computational oblivion.
Unfortunately, some applications do not use the system logging
interface by default. The squid proxy server is one such example,
storing logs instead in /var/logs as flat text files. Apache httpd does
this as well, again, storing logs as flat text files. There are several
options available to us in this case. I will use the apache http server
as an example here
1. Do nothing. Look up the logs wherever the application stores them;
in this case, /chroot/httpd/var/logs
2. Have a separate partition for /var/log, and mount this inside each
jail you wish to log to this directory. However, this rather defeats
the point of having a chroot jail in the first place – your system logs
are now a part of those jails.
3. Some applications may have an option to use syslog logging instead
of the default. Compile the application with this option, and specify
an additional /dev/log device for these applications.
4. For the über leet, modify the source code to support syslog
logging
We now have a basic application environment installed, and can diagnose
most errors the application will provide for us. We can begin the
process of starting the chrooted service and, more or less, stepping
through the errors one by one and getting it running.
INSTALLING A WORKING ENVIRONMENT IN THE JAIL
It may help at this point to install a working environment inside the
chroot jail, complete with a shell and basic commands such as ls and
rm. I recommend you obtain the coreutils package and compile it
statically. (So it does not depend on shared system libraries which may
not be present in the jail). You will also need a statically compiled
shell, such as bash. Place these utilities in the chroot jail, but make
sure they are in a seperate directory, such as
/chroot/[app]/static-bin, so they may be easily removed later. You will
need at least a symlink from /bin/bash to /static-bin/bash if you are
to be able to chroot into the jail environment. Once these utilities
are installed to /static-bin (inside the jail), and bash is symlinked
from /bin (again, inside the jail), you should be able to chroot to the
new environment with the following command:
Code:
chroot /chroot/mysql
The root directory will now be /chroot/mysql. You are seeing exactly
what the MySQL server will see when it runs chrooted. MAKE SURE TO
REMOVE THESE TOOLS FROM THE JAIL WHEN YOU NO LONGER NEED THEM. Their
presence could be exploited remotely if the service is compromised.
Hopefully, we will not need this temporary environment, but it will not
hurt to have it, just in case. I have required it to diagnose errors on
more than one occasion.
Original Tutorial
Submitted by Striek for TheTAZZone-TAZForum
Originally posted on June 11th, 2006 here
Do not use, republish, in whole or in part, without the consent of
the Author. TheTAZZone policy is that Authors retain the rights to the
work they submit and/or post...we do not sell, publish, transmit, or
have the right to give permission for such...TheTAZZone merely retains
the right to use, retain, and publish submitted work within it's
Network.

