Clone wiki

unionfs-chroot / Home


This repository has a shell script to automate a common useful task for quarantining processes which are "poorly behaved" with respect to which files they modify in the underlying system, such as many build or install systems.

Disclaimer: This technique is not a security barrier.


This depends on the unionfs-fuse tool, which is in a Debian/Ubuntu package of the same name.


Suppose you've just downloaded some software, but you don't have faith that when you run make install it won't clobber your base filesystem, such as by overwriting a file in /etc or otherwise interfering with your distribution.

Packages with "well behaved" installers will accept an installation target, and then they will only write files under that directory. For example, packages distributed with autoconf will typically support a --prefix option to ./configure. How can you be sure the package is well behaved?

You could read all the source code to the installation code, but this is time consuming. Furthermore, maybe this package is an opaque non-open-source distribution, such as for a proprietary driver.

Here is how to use this script to quarantine the installation and examine it after the fact:

$ unionfs-chroot
Quarantining all fs writes into: /tmp/tmp.1GbGIk241B_unionfs-chroot.sandbox
Running: sudo unionfs-fuse -o allow_other,use_ino,suid,dev,nonempty -ocow /tmp/tmp.1GbGIk241B_unionfs-chroot.sandbox=RW:/=RO /tmp/tmp.bQUprjB0zZ_unionfs-chroot.mountpoint
Running: sudo chroot /tmp/tmp.bQUprjB0zZ_unionfs-chroot.mountpoint /bin/su - myuser

The script tells us where it is saving all sandboxed writes to. We did not specify a specific directory on the commandline, so it made a temporary directory (ending with _unionfs-chroot.sandbox).

We are actually now running in a sub-shell from the original shell as the last Running: output shows. We can verify that we are in a unionfs-chroot sandbox by looking for a specially named file:

$ cat /unionfs-chroot.sandbox

This file contains the path in the outside world of the sandbox directory.

Now we can run the build process without worrying that a (non-malicious) installer will clobber our base system:

$ cd ./src/some_package
$ make install

After this we can close this shell and examine the contents of the sandbox:

$ ^D
Running: sudo umount /tmp/tmp.bQUprjB0zZ_unionfs-chroot.mountpoint

The script unmounts the unionfs and removes the (empty) mountpoint directory. Now we can do a sanity check that we are not inside a sandbox:

$ cat /unionfs-chroot.sandbox
cat: /unionfs-chroot.sandbox: No such file or directory

Now we can see what the installer actually wrote to the filesystem:

$ cd /tmp/tmp.1GbGIk241B_unionfs-chroot.sandbox
$ find

If we want to accept these modifications, we have two options:

Copying to integrate changes

We can "accept" the changes made by the installer by doing a recursive, attribute-preserving copy:

Warning: Make extra sure this is the right command. I have not tested this, and claim no responsibility for breaking your system! I chose to copy into /usr/local in an attempt to avoid clobbering the base system's distro state.

Warning: If a file written into the sandbox would overwrite a base system file, it is possible that another process modified that underlying file while the installer was operating in the sandbox. In this case, copying the sandbox over the base system would erase some changes.

$ cp -a /tmp/tmp.1GbGIk241B_unionfs-chroot.sandbox/ /usr/local

Re-entering the sandboxed union mount

Another option is to re-enter the union mount every time you want to use the given software. This has the tradeoff that any data written by the installed package's processes (or any other processes invoked in the sandbox) will also be quarantined.

This might be useful, for example, if you want to run firefox in two different sandboxes to help ensure they are not leaking privacy-related state between each sandbox.

The script accepts a sandbox as the first argument, so this allows us to re-use a sandbox:

$ /tmp/tmp.1GbGIk241B_unionfs-chroot.sandbox  
Quarantining all fs writes into: /tmp/tmp.1GbGIk241B_unionfs-chroot.sandbox
Running: sudo unionfs-fuse -o allow_other,use_ino,suid,dev,nonempty -ocow /tmp/tmp.1GbGIk241B_unionfs-chroot.sandbox=RW:/=RO /tmp/tmp.i5Qh33JoEl_unionfs-chroot.mountpoint
Running: sudo chroot /tmp/tmp.i5Qh33JoEl_unionfs-chroot.mountpoint /bin/su - myuser
$ cat /unionfs-chroot.sandbox 

Now you can run the "installed" package.


Q. Do recursive sandboxes work?

A. I don't know yet; I have not tested it.

Any other questions? Please contact the developer.