mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-02 15:25:27 +00:00
Libvirt: initial markdown conversion
241
Libvirt.md
Normal file
241
Libvirt.md
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
With cloud computing and virtualization becoming more and
|
||||||
|
more prevalent, improving the security stance for libvirt
|
||||||
|
users is of primary concern. As of libvirt 0.7.2, AppArmor
|
||||||
|
support for confining virtual machines is available. This
|
||||||
|
tutorial is an updated version of [Jamie Strandboge's blog
|
||||||
|
entry](http://penguindroppings.wordpress.com/2009/11/03/apparmor-svirt-security-driver-for-libvirt/)
|
||||||
|
announcing the availability of an AppArmor-enabled libvirt in Ubuntu
|
||||||
|
9.10 (by permission). The libvirt AppArmor driver uses the sVirt
|
||||||
|
framework within libvirt, which is used to confine QEMU (and KVM)
|
||||||
|
virtual machines and as of libvirt 1.2.3, libvirt-lxc containers.
|
||||||
|
|
||||||
|
Implementation Overview
|
||||||
|
=======================
|
||||||
|
|
||||||
|
First, the libvirtd process is considered trusted and is therefore
|
||||||
|
confined with a lenient profile that allows the libvirt daemon to
|
||||||
|
launch VMs or containers, change into another AppArmor profile and
|
||||||
|
use virt-aa-helper to manipulate AppArmor profiles. virt-aa-helper
|
||||||
|
is a helper application that can add, remove, modify, load and
|
||||||
|
unload AppArmor profiles in a limited and restricted way. libvirtd
|
||||||
|
is not allowed to adjust anything in /sys/kernel/security directly,
|
||||||
|
or modify the profiles for the virtual machines directly. Instead,
|
||||||
|
libvirtd must use virt-aa-helper, which is itself run under a
|
||||||
|
very restrictive AppArmor profile. Using this architecture helps
|
||||||
|
prevent any opportunities for a subverted libvirtd to change its own
|
||||||
|
profile (especially useful if the libvirtd profile is adjusted to be
|
||||||
|
restrictive) or modify other AppArmor profiles on the system.
|
||||||
|
|
||||||
|
Next, there are several profiles that comprise the system:
|
||||||
|
|
||||||
|
```
|
||||||
|
/etc/apparmor.d/usr.sbin.libvirtd
|
||||||
|
/etc/apparmor.d/usr.lib.virt-aa-helper
|
||||||
|
/etc/apparmor.d/abstractions/libvirt-qemu
|
||||||
|
/etc/apparmor.d/abstractions/libvirt-lxc # libvirt 1.2.9+
|
||||||
|
/etc/apparmor.d/libvirt/TEMPLATE # libvirt 1.2.2 and lower
|
||||||
|
/etc/apparmor.d/libvirt/TEMPLATE.qemu # libvirt 1.2.3+
|
||||||
|
/etc/apparmor.d/libvirt/TEMPLATE.lxc # libvirt 1.2.3+
|
||||||
|
/etc/apparmor.d/libvirt/libvirt-<uuid>
|
||||||
|
/etc/apparmor.d/libvirt/libvirt-<uuid>.files
|
||||||
|
```
|
||||||
|
|
||||||
|
**/etc/apparmor.d/usr.sbin.libvirtd** and
|
||||||
|
**/etc/apparmor.d/usr.lib.virt-aa-helper**
|
||||||
|
define the profiles for libvirtd and
|
||||||
|
virt-aa-helper. **/etc/apparmor.d/libvirt/TEMPLATE\[.qemu|.lxc\]**
|
||||||
|
is consulted when creating a new profile when one does not
|
||||||
|
already exist. **/etc/apparmor.d/abstractions/libvirt-qemu**
|
||||||
|
is the abstraction shared by all running VMs with
|
||||||
|
**/etc/apparmor.d/abstractions/libvirt-lxc** for libvirt-lxc
|
||||||
|
containers. **/etc/apparmor.d/libvirt/libvirt-<uuid>** is
|
||||||
|
the unique base profile for an individual VM/container, and
|
||||||
|
**/etc/apparmor.d/libvirt/libvirt-<uuid>.files** contains rules for
|
||||||
|
the guest-specific files required to run this individual VM/container.
|
||||||
|
|
||||||
|
The confinement process is as follows (assume the VM/container has
|
||||||
|
a libvirt UUID of 'a22e3930-d87a-584e-22b2-1d8950212bac'):
|
||||||
|
|
||||||
|
- When libvirtd is started, it determines if it should use
|
||||||
|
a security driver. If so, it checks which driver to use (eg
|
||||||
|
SELinux or AppArmor). If libvirtd is both confined by AppArmor
|
||||||
|
and configured to use it in /etc/libvirt/qemu.conf, it will use
|
||||||
|
the AppArmor security driver
|
||||||
|
|
||||||
|
- When a VM/container is started, libvirtd decides whether
|
||||||
|
to ask virt-aa-helper to create a new profile or modify
|
||||||
|
an existing one. If no profile exists, libvirtd asks
|
||||||
|
virt-aa-helper to generate the new base profile, in this case
|
||||||
|
/etc/apparmor.d/libvirt/libvirt-a22e3930-d87a-584e-22b2-1d8950212bac,
|
||||||
|
which it does based on
|
||||||
|
/etc/apparmor.d/libvirt/TEMPLATE\[.qemu|.lxc\]. Notice,
|
||||||
|
the new profile has a profile name that is based on
|
||||||
|
the guest’s UUID. Once the base profile is created,
|
||||||
|
virt-aa-helper works the same for create and modify:
|
||||||
|
virt-aa-helper will determine what files are required for
|
||||||
|
the guest to run (eg kernel, initrd, disk, serial, etc), updates
|
||||||
|
/etc/apparmor.d/libvirt/libvirt-a22e3930-d87a-584e-22b2-1d8950212bac.files,
|
||||||
|
then loads the profile into the kernel.
|
||||||
|
|
||||||
|
- libvirtd will proceed as normal at this point, until just
|
||||||
|
before it forks a qemu/kvm/container process, it will
|
||||||
|
call aa\_change\_profile() to transition into the profile
|
||||||
|
‘libvirt-a22e3930-d87a-584e-22b2-1d8950212bac’ (the one
|
||||||
|
virt-aa-helper loaded into the kernel in the previous step)
|
||||||
|
|
||||||
|
- When the VM/container is shutdown, libvirtd asks virt-aa-helper
|
||||||
|
to remove the profile, and virt-aa-helper unloads the profile
|
||||||
|
from the kernel
|
||||||
|
|
||||||
|
It should be noted that due to current limitations of AppArmor, only
|
||||||
|
qemu:///system and lxc:// are confined by AppArmor. In practice, this
|
||||||
|
is fine because qemu:///session is run as a normal user and does not
|
||||||
|
have privileged access to the system like qemu:///system does.
|
||||||
|
|
||||||
|
Basic Usage
|
||||||
|
===========
|
||||||
|
|
||||||
|
To see if libvirtd is using the AppArmor security driver, do:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ virsh capabilities
|
||||||
|
Connecting to uri: qemu:///system
|
||||||
|
<capabilities>
|
||||||
|
<host>
|
||||||
|
...
|
||||||
|
<secmodel>
|
||||||
|
<model>apparmor</model>
|
||||||
|
<doi>0</doi>
|
||||||
|
</secmodel>
|
||||||
|
</host>
|
||||||
|
...
|
||||||
|
</capabilities>
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, start a VM and see if it is confined:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ virsh start testqemu
|
||||||
|
Connecting to uri: qemu:///system
|
||||||
|
Domain testqemu started
|
||||||
|
$ virsh domuuid testqemu
|
||||||
|
Connecting to uri: qemu:///system
|
||||||
|
a22e3930-d87a-584e-22b2-1d8950212bac
|
||||||
|
$ sudo aa-status
|
||||||
|
apparmor module is loaded.
|
||||||
|
16 profiles are loaded.
|
||||||
|
16 profiles are in enforce mode.
|
||||||
|
...
|
||||||
|
/usr/bin/virt-aa-helper
|
||||||
|
/usr/sbin/libvirtd
|
||||||
|
libvirt-a22e3930-d87a-584e-22b2-1d8950212bac
|
||||||
|
...
|
||||||
|
0 profiles are in complain mode.
|
||||||
|
6 processes have profiles defined.
|
||||||
|
6 processes are in enforce mode :
|
||||||
|
...
|
||||||
|
libvirt-a22e3930-d87a-584e-22b2-1d8950212bac (6089)
|
||||||
|
...
|
||||||
|
0 processes are in complain mode.
|
||||||
|
0 processes are unconfined but have a profile defined.
|
||||||
|
$ ps ww 6089
|
||||||
|
PID TTY STAT TIME COMMAND
|
||||||
|
6089 ? R 0:00 /usr/bin/qemu-system-x86_64 -S -M pc-0.11 -no-kvm -m 64 -smp 1 -name testqemu -uuid a22e3930-d87a-584e-22b2-1d8950212bac -monitor unix:/var/run/libvirt/qemu/testqemu.monitor,server,nowait -boot c -drive file=/var/lib/libvirt/images/testqemu.img,if=ide,index=0,boot=on -drive file=,if=ide,media=cdrom,index=2 -net nic,macaddr=52:54:00:86:5b:6e,vlan=0,model=virtio,name=virtio.0 -net tap,fd=17,vlan=0,name=tap.0 -serial none -parallel none -usb -vnc 127.0.0.1:1 -k en-us -vga cirrus
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is the unique, restrictive profile for this VM:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat /etc/apparmor.d/libvirt/libvirt-a22e3930-d87a-584e-22b2-1d8950212bac
|
||||||
|
#
|
||||||
|
# This profile is for the domain whose UUID
|
||||||
|
# matches this file.
|
||||||
|
#
|
||||||
|
|
||||||
|
#include <tunables/global>
|
||||||
|
|
||||||
|
profile libvirt-a22e3930-d87a-584e-22b2-1d8950212bac {
|
||||||
|
#include <abstractions/libvirt-qemu>
|
||||||
|
#include <libvirt/libvirt-a22e3930-d87a-584e-22b2-1d8950212bac.files>
|
||||||
|
}
|
||||||
|
|
||||||
|
$ cat /etc/apparmor.d/libvirt/libvirt-a22e3930-d87a-584e-22b2-1d8950212bac.files
|
||||||
|
# DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.
|
||||||
|
"/var/log/libvirt/**/testqemu.log" w,
|
||||||
|
"/var/run/libvirt/**/testqemu.monitor" rw,
|
||||||
|
"/var/run/libvirt/**/testqemu.pid" rwk,
|
||||||
|
"/var/lib/libvirt/images/testqemu.img" rw,
|
||||||
|
```
|
||||||
|
|
||||||
|
Now shut it down:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ virsh shutdown testqemu
|
||||||
|
Connecting to uri: qemu:///system
|
||||||
|
Domain testqemu is being shutdown
|
||||||
|
|
||||||
|
$ virsh domstate testqemu
|
||||||
|
Connecting to uri: qemu:///system
|
||||||
|
shut off
|
||||||
|
|
||||||
|
$ sudo aa-status | grep 'a22e3930-d87a-584e-22b2-1d8950212bac'
|
||||||
|
[1]
|
||||||
|
```
|
||||||
|
|
||||||
|
Advanced Usage
|
||||||
|
==============
|
||||||
|
|
||||||
|
In general, you can forget about AppArmor confinement and just use
|
||||||
|
libvirt like normal. The guests will be isolated from each other and
|
||||||
|
user-space protection for the host is provided. However, the design
|
||||||
|
allows for a lot of flexibility in the system. For example:
|
||||||
|
|
||||||
|
- If you want to adjust the profile for all
|
||||||
|
future, newly created VM/containers, adjust
|
||||||
|
/etc/apparmor.d/libvirt/TEMPLATE\[.qemu|.lxc\]
|
||||||
|
|
||||||
|
- If you need to adjust access controls for all VM/containers, new or
|
||||||
|
existing, adjust /etc/apparmor.d/abstractions/libvirt{-qemu,-lxc}
|
||||||
|
|
||||||
|
- If you need to adjust access controls for a single guest, adjust
|
||||||
|
/etc/apparmor.d/libvirt-<uuid>, where <uuid> is the UUID of
|
||||||
|
the guest
|
||||||
|
|
||||||
|
- To disable the driver, either adjust /etc/libvirt/qemu.conf to have
|
||||||
|
'security\_driver = “none”' or remove the AppArmor profile
|
||||||
|
for libvirtd from the kernel and restart libvirtd
|
||||||
|
|
||||||
|
Of course, you can also adjust the profiles for libvirtd and
|
||||||
|
virt-aa-helper if desired. All the files are simple text files.
|
||||||
|
|
||||||
|
Limitations and the Future
|
||||||
|
==========================
|
||||||
|
|
||||||
|
While the sVirt framework provides good guest isolation and user-space
|
||||||
|
host protection, the framework does not provide protection against
|
||||||
|
in-kernel attacks (eg, where a guest process is able to access the host
|
||||||
|
kernel memory). Once AppArmor provides the ability for regular users
|
||||||
|
to define profiles, then qemu:///session can be properly supported.
|
||||||
|
|
||||||
|
Summary
|
||||||
|
=======
|
||||||
|
|
||||||
|
With cloud computing and virtualization becoming even more important
|
||||||
|
in the data center, leveraging technologies like libvirt and AppArmor
|
||||||
|
is a must. Virtualization removes the traditional barriers afforded
|
||||||
|
to stand-alone computers, thus increasing the attack surface for
|
||||||
|
hostile users and compromised guests. By using the sVirt framework
|
||||||
|
in libvirt administrators can better defend themselves against
|
||||||
|
virtualization-specific attacks.
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
- http://libvirt.org/
|
||||||
|
- http://danwalsh.livejournal.com/30565.html
|
||||||
|
- http://lwn.net/Articles/353970/
|
||||||
|
- http://penguindroppings.wordpress.com/2009/11/03/apparmor-svirt-security-driver-for-libvirt/
|
||||||
|
|
Reference in New Issue
Block a user