Compartmentalisation by means of virtualisation

Fabio Natali, 28 April 2024

Intro

Now and then I find myself having to open a file or an application that I don't fully trust. A common technique to deal with this is to create a disposable environment (for example a so-called container or a virtual machine) where the file or application can be safely opened. Once used, the environment can be discarded.

This technique is known as compartmentalisation and is so established in information security that there's an entire operating systems, Qubes OS, based on it. Qubes OS hugely facilitates the task of working across a number of isolated environments. If you're like me, you may need compartmentalisation only for specific tasks and not often enough to necessarily require Qubes OS (although some of its principles should be adopted more broadly by other operating systems).

Personally, when I do need compartmentalisation, I tend to leverage some features and tools offered by my operating system, GNU Guix. This is a short write-up on my use of containers and virtual machines for compartmentalisation under Guix. I'm not presenting anything new, this is just a note-to-self for when I need to refresh my memory and copy-and-paste a couple of commands.

Containers

Containers (i.e. operating-system virtualisation like with Linux Containers, Docker, and Podman) are a way for the operating system's kernel to isolate one or more processes and resources from the rest of the system. Containers are an example of lightweight compartmentalisation, i.e. they are cheap in terms of resource consumption but typically their isolation is not as strong as with virtual machines.

Guix makes it very easy to use containers. This is already well explained in the Guix Reference Manual and in the Guix Cookbook. One example provided in the manual is around running a security-sensitive application, the "ungoogled" version of the Chroumium web browser, in an isoltated environment:

guix shell \
     --container \
     --network \
     --no-cwd \
     ungoogled-chromium \
     --expose="${XAUTHORITY}" \
     --preserve="^XAUTHORITY$" \
     --preserve="^DISPLAY$" \
     -- chromium

Under this setup, in order to compromise the system, a malicious web page would have to exploit a browser vulnerability and also escape the constraints of the Guix container.

Virtual machines

Virtual machines (i.e. hardware virtualisation via a hypervisor such as KVM+QEMU) are also a mechanism to create isolated environments. In this case, the guest system (i.e. the isolated environment as opposed to the main system or host) behaves as if it were a separate machine with its own operating system (and possibly a different architecture). Virtual machines typically provide a stronger level of isolation than containers.

Using virtual machines as sandboxes is not as straightforward as running a container with guix shell --container, but it's still relatively simple. In the following example, we want to open an untrusted Microsoft Word document with LibreOffice from within a virtual machine.

We follow these steps:

  • Create a minimalist Guix system image that includes LibreOffice.
  • Launch a virtual machine and share the untrusted files with it.
  • Log in to the virtual machine to open an untrusted Word document.

A minimalist Guix system image

Here's a minimalist Guix system definition that includes LibreOffice.

(define-module (operating-system-base)
  #:use-module (gnu)
  #:use-module (gnu services desktop)
  #:use-module (gnu packages libreoffice)
  #:use-module (gnu packages wm)
  #:use-module (gnu packages xorg)
  #:export (operating-system-base))

(define operating-system-base
  (operating-system
    (host-name "host")
    (bootloader (bootloader-configuration
                 (bootloader grub-bootloader)
                 (targets '("/dev/vda"))))
    (file-systems (cons
                   (file-system
                     (device "/dev/vda1")
                     (mount-point "/")
                     (type "ext4"))
                   %base-file-systems))
    (packages (cons*
               i3-wm
               libreoffice
               xterm
               %base-packages))
    (services %desktop-services)))

operating-system-base

The definition can be built and instantiated with a single Guix command, as follows. Under the hood, this uses KVM+QEMU to launch a virtual machine. A folder is shared in read-only mode (i.e. exposed) so that relevant files can be passed from the host to the guest system.

$(guix system vm os.scm --expose=/path/to/shared/folder) -m 4096

Once the system has started, login as root, then open a terminal with i3's default key binding, usually M-RET. You can now open the file from within the virtual machine with:

libreoffice /path/to/shared/folder/file.odt

Outro

Guix provides at least a couple of mechanisms to open files and applications in isolated environments. Containerisation is the simplest alternative, you just use guix shell --container. When a stronger form of isolation is necessary, one can easily create a Guix image that includes the necessary software and run it with guix system vm. Files can be exchanged between the host and guest system via --expose. Pretty cool ways of launching a sandbox!

Revision 78086bc.