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:
|| border=1 width=100%25 class="sortable simpletable"
||# Chrooted OpenBSD daemons ||||
||# Application ||# Chroot path ||
|| openhttpd || /var/www/
||
|| nsd || /var/nsd/
||
|| unbound || /var/unbound/
||# Chrooted third party daemons ||||
||# Application ||# Chroot 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:
It requires you replicate each dependency inside the chroot every time you install or update the program
It cannot limit the type of syscalls that the process can make
It requires you call it as root, so normal users cannot run them
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.