Chroot: Intro

Chroot refers to changing the root. When a process runs inside a chroot, you change what the process thinks is its root directory.

Normally, a process can access any file within the root filesystem it has permissions for. By changing what the process thinks is its root directory, however, the process is now stuck in a chroot "jail".

This provides enhanced security: if a program gets compromised, it can only access and modify files within the new root.

Uses

Many OpenBSD daemons and third-party applications can be chrooted:

Chrooted OpenBSD daemons
ApplicationChroot path
openhttpd/var/www/
nsd/var/nsd/
unbound/var/unbound/
Chrooted third party daemons
ApplicationChroot path
ngircd/var/ngircd/
znc/home/znc/
wraith?/home/wraith/
pylink/home/pylink/

Creating a Chroot

Suppose for a moment we want to chroot an imaginary program. We first call whereis on the binary to find its absolute path:

$ whereis program
/usr/bin/program

Next, we call ldd on the absolute path to find its dependencies:

$ ldd /usr/bin/program
/usr/bin/program
        Start            End              Type  Open Ref GrpRef Name
        0000022622dc8000 0000022622dcd000 exe   1    0   0      /usr/bin/program
        000002285bdc7000 000002285c133000 rlib  0    1   0      /usr/lib/libprogram.so.20.0
        00000228c7de6000 00000228c7e16000 rlib  0    2   0      /usr/lib/libm.so.10.1
        000002282f00d000 000002282f101000 rlib  0    2   0      /usr/lib/libc.so.96.0
        0000022914fb2000 0000022914fb2000 ld.so 0    1   0      /usr/libexec/ld.so

We must re-create the filesystem in our chroot, /home/program, and copy all necessary dependencies:

$ doas mkdir -p /home/program/usr/bin/
$ doas mkdir -p /home/program/usr/lib/
$ doas mkdir -p /home/program/usr/libexec/
$ doas cp /usr/bin/program /home/program/usr/bin/
$ doas cp /usr/lib/libprogram.so.20.0 /home/program/usr/lib/
$ doas cp /usr/lib/libm.so.10.1 /home/program/usr/lib/
$ doas cp /usr/lib/libc.so.96.0 /home/program/usr/lib/
$ doas cp /usr/libexec/ld.so /home/program/usr/libexec/

Then, to run the chroot:

$ doas chroot -u daemon -g daemon /home/program program

Sometimes, these dependencies have their own dependencies, so you may need to run ldd and copy files multiple times. Some of these dependencies do not become apparent until you attempt to run the program.

Drawbacks

There are many drawbacks to using a chroot:

  1. It requires you replicate each dependency inside the chroot every time you install or update the program
  2. It cannot limit the type of syscalls that the process can make
  3. It requires you call it as root, so normal users cannot run them
  4. Chrooted processes still have access to the network

Because of these limitations of a chroot, OpenBSD developed pledge and unveil to tighten the security of a process, however a simpler approach could be plan 9's private namespaces.