On Tue, Mar 08, 2016 at 04:24:51PM +0000, Matthew Booth wrote:
Nova just released a fix for this critical CVE:
https://bugs.launchpad.net/nova/+bug/1548450
To summarise, it's a qcow2 backing file exploit. The user writes a
malicious qcow2 header to the top of a raw disk, then triggers a bug in
Nova which causes it to do format detection.
If you read the bug and comments, you'll see that when I initially reported
it I was fairly dismissive of its impact because it's only exploitable
through libvirt, and the instance is going to be confined by SELinux. But
then Dan B points out that sVirt is going to trust whatever Nova tells it
to do and label it appropriately. Cue rapid ramping of severity, and it
turns out this allows an unprivileged user to read anything on the host,
including all raw block devices.
I'm not sure exactly where, but something in this stack has failed us.
Let's be clear a couple of things, though:
1. This is an egregious, stupid bug in Nova, and Nova shouldn't have
egregious, stupid bugs.
2. SELinux should prevent obviously bad things from happening, even in the
presence of egregious, stupid bugs.
I point that out to head off: 'Well Nova shouldn't do that'. Of course it
shouldn't. However, it might, and when it does, I'd like to think that
SELinux has its back. It doesn't, though.
As I understand it, sVirt is the mechanism libvirt uses for controlling
SELinux. I wonder if the current sVirt model is enough to cover the use
case where the thing connecting to libvirt is large enough to have its own
serious bugs. Is there any way we could define a sane set of operations
independent of Nova?
You need to distinguish SELinux and sVirt in this discussion.
What I mean by this is that SELinux refers to the general MAC framework
that is limited only by the smarts of the person designing the policy.
It is entirely possible to write an SELinux policy that prevents libvirtd
from doing whatever it likes. Whether it is *practical* to write such a
policy that works in a general purpose linux host is a different issue,
I'll come back to shortly...
sVirt refers to the use of MAC to mitigate against bugs in guest VMs that
would otherwise allow a compromised VM to attack other VMs or the host. It
is an explicit *non-goal* of sVirt to protect the host from applications
connected to libvirt. Or to put it another way, as far as sVirt is concerned,
it is an explicitly assumed that the application configuring libvirt guests
knows what it is doing. sVirt will honour whatever it is told to allow the
guest todo. This design decision was fundamental to making sVirt something
that was practical to actually run with zero-configuration on any Linux
host with virtualization. Libvirt does not want to define or impose policy
on usage of its APIs, by default, it wants to provide the mechanism and
leave policy up to the virt mgmt application to decide what's acceptable
or not.
So for both reasons of practicality (to hard to enumerate what is valid
todo via libvirt without blocking valid use cases) and design (we explicitly
don't want to be second guessing what apps might consider valid), the
libvirtd daemon SELinux policy is essentially equivalent to unconfined_t.
Thus applications connecting to privileged libvirtd are considered to have
privileges equivalent to root, and it is their responsibility to tell
libvirt todo sensible things.
I don't see us changing this as a default out of the box approach, because
defining valid usage policy is a fundamentally hard problem and would likely
just result in giving you a false sense of security.
For example, consider you wrote some policy rule that prevented libvirtd
from relabelling /dev/sda to allow access by a guest because /dev/sda was
your host root filesystem device. You might think you are now secure ?
Wrong. Nova still has ability to relabel /lib/libc.so and expose this
shared library as /dev/vda in the guest. The malicious guest now writes
to this disk inserting a backdoor in the 'open' function. A completely
different process running on the host will happily now execute that
backdoor as whatever privileges they have (probably unconfined_t.
Ok, so now we blacklist /lib/*. Better do the same for /bin, and /etc
too, oh but we explicitly want access to some files in /etc. We better
black list /var too, but by valid VM config XYZ requires access to
/var/foo/bar. And so on.
This is the problem with confining privileged mgmt applications on a
general purpose Linux install. Now if there was a *non-general purpose*
compute host image whose sole job was to run nova-compute, that would be
a different matter. There are a (hopefulyl) finite number of things that
a nova-compute instance should be permitted todo. So you could write a
SELinux policy for libvirtd, that was targetted solely to Nova that could
give you some better protection.
Such a policy isn't really something for libvirt to care about though - it
is entirely upto the application using libvirt to decide if it wants to
create a custom SELinux policy to confine libvirtd.
Regards,
Daniel
--
|:
http://berrange.com -o-
http://www.flickr.com/photos/dberrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|:
http://entangle-photo.org -o-
http://live.gnome.org/gtk-vnc :|