Libvirt itself runs under a rather lenient profile as it needs to do so much, but the more important concerns are around breaking out of the guest. To further limit the damage in case such athing happend on Ubuntu Libvirt will by default wrap each qemu/kvm guest in it's own custom apparmor profile.
This profile consists of:
the base profile qemu/kvm always needs in /etc/apparmor.d/abstractions/libvirt-qemu
a generated per guest profile /etc/apparmor.d/libvirt/libvirt-<guestUUID>
For example every guest will need access to /dev/kvm and there is no reason to isolate that. But the for example there is no reason for a disk of a guest to be allowed to any other guest. For the latter the per guest profiles will be created from the XML description of the guest when it is started.
This conversion from Guest XML to the apparmor profile is done by the tool virt-aa-helper that usually is in /usr/lib/libvirt/virt-aa-helper. Virt-aa-helper needs to do some checks on files to generate rules, so it has it's own apparmor profile in /etc/apparmor.d/usr.lib.libvirt.virt-aa-helper.
If you are unsure about the UUID of your guest check virsh dominfo <guestname> which will report it.
Debugging Virtualization related apparmor issues
The most common issue around this are:
- features unknown to libvirt
- Special characters
- Using uncommon paths
features unknown to libvirt
If you use a new libvirt feature that has no apparmor support yet or more often directly qemu-commandline then virt-aa-helper just can't generate the rule for it.
In the case of qemu-commandline it is - in the XML sense - invisible to virt-aa-helper as it is a different scope.
In these cases you will need to allow access to these paths to the generic base profile in /etc/apparmor.d/abstractions/libvirt-qemu to be accessible.
To know what you need to add check dmesg -w when starting the guest (or attaching the device). This will already let you know the path, the profile and the requested permissions.
This is not so common, but if it happens the error messages are often quite misleading. It might look like:
error: Failed to attach device from disk.xml error: internal error: cannot update AppArmor profile 'libvirt-8763795d-f056-4373-9d57-3d3bad391e5a'
The problem here is that this is only the last of potentially multiple errors that have occurred. In most of the cases you can just attach to the log of journal for this unit. In the above case for example you will see this when the issue triggers:
$ journalctl -f -u libvirtd [...] Jun 20 09:21:57 c libvirtd: 2018-06-20 09:21:57.707+0000: 28490: error : virCommandWait:2601 : internal error: Child process (LIBVIRT_LOG_OUTPUTS=3:stderr /usr/lib/libvirt/virt-aa-helper -p 0 -r -u libvirt-8763795d-f056-4373-9d57-3d3bad391e5a -f '/var/lib/libvirt/images/break,^*", foo"me.qcow') unexpected exit status 1: virt-aa-helper: error: /var/lib/libvirt/images/break,^*", foo"me.qcow Jun 20 09:21:57 c libvirtd: virt-aa-helper: error: skipped restricted file Jun 20 09:21:57 c libvirtd: virt-aa-helper: error: invalid VM definition Jun 20 09:21:57 c libvirtd: 2018-06-20 09:21:57.707+0000: 28490: error : AppArmorSetSecurityImageLabel:848 : internal error: cannot update AppArmor profile 'libvirt-8763795d-f056-4373-9d57-3d3bad391e5a'
Most of the time that is enough to spot what is going on. Note: virsh only shows the last error as it doesn't know how much backend errors are related and to avoid filling up the console becoming unreadable.
If the above is not enough it is generally worth to enable libvirtd logging, but due to its size it also rather exhausting to look at. It can be enabled independently for the frontend tools (environment variable) or the actual daemon - see debug logging on the libvirt website for mroe details.
Using uncommon paths
To be able to add the per-guest rules virt-aa-helper has to inspect e.g. disk files for their backing chain. To be allowed to do so virt-aa-helper has a list of allowed paths that it can access in its own apparmor profile /etc/apparmor.d/usr.lib.libvirt.virt-aa-helper.
If you want it to be able to access other paths you have to edit that profile to allow these more uncommon paths as well. Again dmesg is your helper to identify which apparmor deny actually occurs.