There are two ways to create a chroot jail for BIND.  You can either use the -t option with named, or you can use /usr/sbin/chroot.  Both procedures are provided below.  This article assumes that you are using the updated version of BIND (9.6.1-P3) I wrote about in a previous article.  If you are not using this version of BIND than path names and libraries may not be the same.

In this article I have changed the font color for most of the commands you will need to run instead of putting a shell prompt.  This should make it easier to copy and paste multiple lines of shell commands right from your browser window.  If you going to try to retype the commands instead of copy/paste make sure you pay special attention to the quotation marks.  There is a difference between ‘ and ` and ” in a Unix shell.

Procedure 1: Using -t option to named.
When using -t option to named the executable itself defines the chroot jail environment.  named will execute using the standard location of the shared libraries as well as /etc/passwd and /etc/shadow, and then chroot itself.  This means that you do not have to create a full chroot environment.

1- Create named user and group for named processes and directory ownership
groupadd -g 20000 named
useradd -u 20000 -g 20000 -d /tmp -c "Bind DNS Daemon" -s /bin/false named
passwd -N named

2- Create the chroot jail environment
In this example the root of the chroot jail is going to be /opt/bind.
jail=/opt/bind
mkdir $jail
mkdir -p $jail/dev $jail/usr/local/{etc,sbin,var/run/named,var/named}

A. The $jail/dev directory
The following loop will create all required device files in the chroot jail and set the user, group and permissions correctly.

for DEV in conslog log null poll syscon tcp udp zero
do
MAJ=`ls -lL /dev/$DEV | nawk '{print $5}'`; MAJ=${MAJ%,}
MIN=`ls -lL /dev/$DEV | nawk '{print $6}'`
USER=`ls -lL /dev/$DEV | nawk '{print $3}'`
GROUP=`ls -lL /dev/$DEV | nawk '{print $4}'`
UPERM=`ls -lL /dev/$DEV | cut -c 2-4`
GPERM=`ls -lL /dev/$DEV | cut -c 5-7`
OPERM=`ls -lL /dev/$DEV | cut -c 8-10`
mknod ${jail}/dev/${DEV} c $MAJ $MIN
chown ${USER}:${GROUP} $jail/dev/$DEV
chmod u=${UPERM},g=${GPERM},o=$OPERM $jail/dev/$DEV
done

B. The $jail/usr/local directory
chown named:named $jail/usr/local/var/run/named
cp -p /usr/local/sbin/named  $jail/usr/local/sbin/
cp -p /usr/local/etc/* $jail/usr/local/etc/
cp -pr /usr/local/var/named/* $jail/usr/local/var/named/


Setup your named.conf and zone files in the $jail/usr/local directory structure.

If this DNS server is a slave server then the named user will have to have write permission to the zones directory.  If it is not a slave, this step isn’t necessary.  If you don’t change the permissions or ownership of the zones directory then you’ll see the following message when you start BIND.
[ID 873579 daemon.error] the working directory is not writable
Run the following two command to change the ownership and permissions of the zones directory.
chown named:named $jail/usr/local/var/named
chmod 750 $jail/usr/local/var/named

3- Update the dns/server SMF service to run your new version of BIND in the chroot jail using the named -t option.

svccfg -s dns/server:default
setprop start/user=astring:"named"
setprop start/group=astring:"named"
setprop options/chroot_dir=astring:"/opt/bind"
exit

svcadm refresh dns/server

Then edit the service method to run the named executable from the chroot jail.
# vi /lib/svc/method/dns-server
Change the line that says:
server="/usr/sbin/named"
to
server="/opt/bind/usr/local/sbin/named"

You can now manage your updated and chroot’ed version of BIND with your svcadm commands:
# svcadm enable dns/server
# svcadm disable dns/server
# svcadm restart dns/server

Or you can start named manually
# /opt/bind/usr/local/sbin/named -t /opt/bind -u named

=============================================================================================================================

Procedure 2: Using the /usr/sbin/chroot command
This procedure can be used to create a chroot jail for any binaries, not just named.  (Of course, you’ll have to modify the procedure to fit the executable you’re chroot’ing).  When using the /usr/sbin/chroot binary the change root occurs prior to the execution of the named binary. This means that by the time named executes it’s whole world is bound to the chroot jail.  The result is that all libraries and all configuration files that named depends on will have to be copied into the chroot jail.

Follow steps 1 & 2 from Procedure 1 above and then we’ll just add the necessary libraries and configuration files to that environment.

1- Add required libraries to the chroot jail.
Use the ldd command to get a list of the libraries that the original named binary uses, and copy those libraries over to your chroot jail.
jail=/opt/bind
ldd /usr/local/sbin/named

You will see that there are library files under /lib, /usr/lib, /usr/local/lib and /usr/local/ssl/lib. On SPARC systems you will also have some libraries from /platform/`uname -i`/lib as well.
You can either create these directories under your chroot jail and then copy the libraries over, or you can use the following loop to do all of it for you.

for LIB in `ldd /usr/local/sbin/named | nawk '{print $NF}'`
do
if [ ! -d "`dirname ${jail}${LIB}`"  ]
then
mkdir -p ${jail}`dirname ${LIB}`
fi
cp  $LIB  ${jail}${LIB}
done

A few other libraries are required as well:
cp -p /usr/lib/ld.so.1 $jail/usr/lib
cp -p /lib/nss_files.so.1 $jail/lib

And the zoneinfo library
mkdir -p `dirname $jail/usr/share/lib/zoneinfo/$TZ`
cp -p /usr/share/lib/zoneinfo/$TZ   `dirname $jail/usr/share/lib/zoneinfo/$TZ`

2- The chroot jail will also need to have a passwd, shadow and group file with the named user and group information to start the process.
mkdir $jail/etc
grep named /etc/passwd > $jail/etc/passwd
grep named /etc/shadow  >$jail/etc/shadow
grep named /etc/group > $jail/etc/group

3- Modify the dns/server SMF service to run /usr/sbin/chroot to set the chroot jail for named.
svccfg -s dns/server:default
setprop start/user=astring:"named"
setprop start/group=astring:"named"
setprop options/chroot_dir=astring:""
exit
svcadm refresh dns/server

Then edit the service method
# vi /lib/svc/method/dns-server
Change the line that says:
server="/usr/sbin/named"
to
server="/usr/sbin/chroot /opt/bind /usr/local/sbin/named"

You can now manage your updated and chroot’ed version of BIND with your svcadm commands:
# svcadm enable dns/server
# svcadm disable dns/server
# svcadm restart dns/server

Or you can start named manually
# /usr/sbin/chroot /opt/bind /usr/local/sbin/named -u named