[ Team LiB ] Previous Section Next Section

Recipe 3.15 Restricting Services to Specific Filesystem Directories

3.15.1 Problem

You want to create a chroot cage to restrict a service to a particular directory (and its subdirectories) in your filesystem.

3.15.2 Solution

Create a chroot cage by running the GNU chroot program instead of the service. Pass the service executable as an argument. In other words, change this:

/etc/xinetd.conf or /etc/xinetd.d/myservice:
service myservice
{
        ...
        server       = /usr/sbin/myservice -a -b
        ...
}

into this:

service myservice
{
        ...
        user = root
        server = /usr/sbin/chroot
        server_args = /var/cage /usr/sbin/myservice -a -b
        ...
}

3.15.3 Discussion

chroot takes two arguments: a directory and a program. It forces the program to behave as if the given directory were the root of the filesystem, "/". This effectively prevents the program from accessing any files not under the chroot cage directory, since those files have no names in the chroot'ed view of the filesystem. Even if the program runs with root privileges, it cannot get around this restriction. The system call invoked by chroot (which also is named chroot) is one-way: once it is invoked, there is no system call to undo it in the context of the calling process or its children.

A chroot cage is most effective if the program relinquishes its root privileges after it starts—many daemons can be configured to do this. A root program confined to a chroot cage can still wreak havoc by creating and using new device special files, or maliciously using system calls that are not related to the filesystem (like reboot!).

In normal operation, a program may access many files not directly related to its purpose, and this can restrict the practicality of chroot. You might have to duplicate so much of your filesystem inside the cage as to negate the cage's usefulness—especially if the files are sensitive (e.g., your password file, for authentication), or if they change. In the former case, it's better if the service itself contains special support for chroot, where it can choose to perform the chroot operation after it has accessed all the general system resources it needs. In the latter case, you can use hard links to make files already named outside the cage accessible from inside it—but that works only for files residing on the same filesystem as the cage. Symbolic links will not be effective, as they will be followed in the context of the cage.

In order for chroot to work, it must be run as root, and the given "cage" directory must contain a Linux directory structure sufficient to run myservice. In the preceding example, /var/cage will have to contain /var/cage/usr/sbin/myservice, /var/cage/lib (which must include any libraries that myservice may use), and so forth. Otherwise you'll see errors like:

chroot: cannot execute program_name: No such file or directory

This can be a bit of a detective game. For example, to get this simple command working:

# chroot /var/cage /usr/bin/who

the directory /var/cage will need to mirror:

/usr/bin/who
/lib/ld-linux.so.2
/lib/libc.so.6
/var/log/wtmp
/var/run/utmp

The commands ldd and strings can help identify which shared libraries and which files are used by the service, e.g.:

$ ldd /usr/sbin/myservice
... output...
$ strings /usr/sbin/myservice | grep /
... output...

3.15.4 See Also

chroot(1), xinetd.conf(5), strings(1), ldd(1). If there's no ldd manpage on your system, type ldd —help for usage.

    [ Team LiB ] Previous Section Next Section