Desc: chrooting and other forms of paranoia
File: chroot.txt
Date: 7 May 2003
Auth: Russell Kroll <rkroll@exploits.org>

It has been possible to run the drivers and upsd in a chrooted jail for
some time, but it involved a number of evil hacks.  The 1.3 series adds
much saner chroot behavior, using BIND 9 as an inspiration.

The old way involved creating an entire tree, complete with libraries, a
shell (!), and many auxiliary files.  This was hard to maintain and
could have become an interesting playground for an intruder.  The new
way is minimal, and leaves little in the way of usable materials within
the jail.

This document assumes that you already have created at least one user
account for the software to use.  If you're still letting it fall back
on "nobody", stop right here and go figure that out first.  It also
assumes that you have everything else configured and running happily all
by itself.

Essentially, you need to create your configuration directory and state
path in their own little world, plus a special device or two.

For the purposes of this example, the chroot jail is /chroot/nut.  The
programs have been built with the default prefix, so they are using
/usr/local/ups.  First, create the confpath and bring over a few files.

	mkdir -p /chroot/nut/usr/local/ups/etc
	cd /chroot/nut/usr/local/ups/etc
	cp -a /usr/local/ups/etc/upsd.users .
	cp -a /usr/local/ups/etc/upsd.conf .
	cp -a /usr/local/ups/etc/ups.conf .

I'm using 'cp -a' to maintain the permissions on those files.

Now bring over your state path, maintaining the same permissions as
before.

	mkdir -p /chroot/nut/var/state
	cp -a /var/state/ups /chroot/nut/var/state

Next we must put /etc/localtime inside the jail, or you may get very  
strange readings in your syslog.  You'll know you have this problem if
upsd shows up as UTC in the syslog while the rest of the system doesn't.

	mkdir -p /chroot/nut/etc
	cp /etc/localtime /chroot/nut/etc

Note that this is not "cp -a", since we want to copy the *content*, not
the symlink that it may be on some systems.

Finally, create a tiny bit of /dev so the programs can enter the
background properly - they redirect fds into the bit bucket to make sure
nothing else grabs 0-2.

	mkdir -p /chroot/nut/dev
	cp -a /dev/null /chroot/nut/dev

Try to start your driver(s) and make sure everything fires up as before.

	upsdrvctl -r /chroot/nut -u nutdev start

Once your drivers are running properly, try starting upsd.

	upsd -r /chroot/nut -u nutsrv

Check your syslog.  If nothing is complaining, try running clients like
upsc and upsmon.  If they seem happy, then you're done.

symlinks
--------

After you do this, you will have two copies of many things, like the
confpath and the state path.  I recommend deleting the 'real'
/var/state/ups, replacing it with a symlink to
/chroot/nut/var/state/ups.  That will let other programs reference the
.pid files without a lot of hassle.

You can also do this with your confpath and point /usr/local/ups/etc at
/chroot/nut/usr/local/ups/etc unless you're worried about something
hurting the files inside that directory.  In that case, you should
maintain a 'master' copy and push it into the chroot path after
making changes.

upsdrvctl itself does not chroot, so the ups.conf still needs to be in
the usual confpath.

upsmon
------

This has not yet been applied to upsmon, since it can be quite
complicated when there are notifiers that need to be run.  One
possibility would be for upsmon to have three instances:

	- privileged root parent that listens for a shutdown command

	- unprivileged child that listens for notify events

	- unprivileged chrooted child that does network I/O

This one is messy, and may not happen for some time, if ever.
