This document needs an overview of security principles. Note that Securing your cloud with Xen's advanced security features contains such an overview.
This chapter describes how to secure a Xen system. It describes a number of advanced Xen features which can be used to increase the security of a system.
The basic setup we'll be considering is as follows:
- A system with an IOMMU with interrupt re-routing.
- For AMD systems, this should be any system with an IOMMU.
- For Intel systems, this should be any system with VT-d version 2 or later.
- Two network cards, attached to the following networks:
- control network: isolated from the internet and from guests. dom0 listens on this network
- guest network: Access to guests and the internet. Domain 0 not accessible from this network.
All the general advice for servers, regarding starting as few services as possible and firewalling off ports applies.
For the purposes of this page, we assume that an attacker has complete control over the kernel of one of the VMs. We also assume that she can inject arbitrary packets into the guest network (either from a VM or from the internet). Our goal is to keep her from being able to read or modify the memory of other guests.
Network driver: Driver domains
The first attack surface to consider is the networking infrastructure. This includes the hardware driver for the network interface card, as well as the bridging software (Linux bridge-utils or open vswitch), and the network backend.
The best way to secure this is to use a driver domain for the guest network. Information on how to set up a driver domain can be found here: Driver_Domain
Secure grub for pv domains: pvgrub
The second attack surface to consider is in respect to PV booting. The default for PV domains is for dom0 to pass the kernel to the domain builder. This is secure, but requires the administrator to keep up to date with kernel updates. It is also less convenient for the user, who can now no longer choose their own kernel parameters.
The first alternative is to use pygrub. Pygrub is a python program that runs in domain 0. It reads the guest filesystem, finds the grub config files, interprets them to present a menu, then reads the selected file off the guest disk and passes it to the domain zero.
The problem is that pygrub and the domain builder run in domain 0, the builder with full privileges to anything on the system. This makes them a juicy target for an attacker; any bug in python, the grub interpreter, the filesystem library, or the domain builder could be exploited to get full control of the system.
The solution is to use pvgrub, a version of grub ported to run on minios. When using pvgrub, the domain builder will build the domain with the full amount of memory, but will start an image containing just minios and pvgrub. pvgrub runs inside the new guest and will display the menu, and load and kexec the appropriate kernel.
Because pvgrub runs inside the guest context, it has no more privileges than the guest already has; there is therefore no benefit to attacking it.
pvgrub can be run by simply setting the kernel in the guest config to point to the appropriate pvgrub image. Instructions for doing can be found here: PvGrub
Securing HVM domains: device model stub domains
The next attack target to consider is qemu. HVM domains use qemu to provide emulated hardware (also known as the "device model"), typically including a motherboard, pci bus, mouse, cdrom, and sometimes disk or network controllers as well.
In the default configuration, qemu runs inside of dom0, and has permission to read or write from any VM on the system, again providing an attractive target. Hardware devices can have complicated interfaces, and the code is not always written with security in mind.
The solution is to run "device model stub domains". A stub domain is a domain with a minimal OS designed to run a single application; in this case, qemu.
Using device models is as simple as changing a setting in the config file. You can read more about setting them up here: Device_Model_Stub_Domains.
Experimental: Using FLASK's example policy
We've discussed securing various codebases outside of the hypervisor. But what about Xen itself? Both PV and HVM guests can attack Xen itself through the hypercall interface. While the Xen developers try to be very careful with the security of the hypercall interface, and now regularly do "fuzz testing" on it to discover potential vulnerabilities, it is inevitable that they will make some mistakes.
One of the ways to mitigate mistakes in the hypercall layer is to use the Xen Security Module (XSM) with FLASK. FLASK is a plugin for XSM written by the NSA, and is Xen's analog of the SELinux security framework. It allows you to load policies to restrict what hypercalls a VM can try to make. Although this doesn't guarantee that no vulnerabilities will be exposed, by restricting what hypercalls are valid, it reduces the probability of an exploitable vulnerability significantly.
FLASK is a mature piece of software, but writing policies is a very tricky and difficult task -- not for the faint of heart. Xen does come with a useful set of "example" policies, which cover most roles that a typical installation would need to use; including driver domains, normal domains, stub domains, and so on. However, these example policies are not heavily tested; they should be used at your own risk.
The basic steps to use FLASK's example policies are as follows:
- Build Xen with XSM enabled
- Build the example policy
- Add the appropriate "labels" to the VM config files, using
seclabel=[$foo], based on their role.
For more information, please see Xen_Security_Modules_:_XSM-FLASK