On Wed, Jul 20, 2011 at 9:17 PM, Eric Blake <eblake(a)redhat.com> wrote:
On 07/20/2011 12:00 PM, Blue Swirl wrote:
>>>
>>> Let's have files A, B, C etc. with backing files AA etc. How would
>>> libvirt know that when QEMU wants to write to file CA, this is because
>>> it's needed to access C, or is it just trickery by a devious guest to
>>> corrupt storage?
>>
>> The fix for CVE-2010-2238 already deals with this: if primary image C
>> refers
>> to backing file CA of raw format, but does not state what file format CA
>> contains, then a malicious guest can modify the contents of CA to appear
>> to
>> be yet another qcow2 image. At which point, if libvirt follows the
>> backing
>> file specified in CA, then yes, the malicious guest really can cause
>> libvirt
>> to expose arbitrary file CB for manipulation by the guest. But that
>> security hole was already plugged - by default, libvirt refuses to probe
>> backing files parsed from qcow2 headers for file format, but instead
>> requires the outer qcow2 header to also include the a file format
>> designation for the backing file. At which point, you then have a safe
>> chain: if C refers to CA, then libvirt knows that both C and CA are
>> essential to the storage presented by giving qemu the file name C, and
>> the
>> guest will already be modifying CA, but there is no storage corruption
>> involved.
>
> But what if CA is accessed even if C is not? For example, QEMU opens C
> (to determine CA and write new information about the path), closes it
> and then requests CA?
Why is qemu trying to access CA?
Either because CA was mentioned as a backing file for C (in which case
libvirt already knows about it, because either libvirt handed C to qemu at
startup time after already parsing C's headers to learn that CA is a backing
file, or because libvirt called the snapshot_blkdev command with the intent
of having qemu populate CA with C as its backing file), or because qemu has
a bug (in which case, libvirt should refuse the access to CA).
So no new backing files can be introduced by QEMU after it has started
without libvirt knowing it?
Libvirt is already perfectly capable of tracking all files that qemu
might
need to access, and whether it is qemu or libvirt that does the open() of
those files, we can still have libvirt validate whether each request for a
file makes sense given the context of all previous files in use from the
time the qemu command line was invoked and across all monitor commands in
the meantime.
On non-NFS solutions, where every file can have a SELinux label, then the
security is then present by merely having libvirt relabel all such files to
a unique label for that particular qemu process, and SELinux merely enforces
that qemu cannot open() anything but what libvirt has already labeled. And
since libvirt already knows which files to label in the non-NFS scenario, it
already knows which fds to pass in the NFS scenario, at which point the
ability to prevent qemu from open()ing an NFS file is a security
enhancement.
Your question about qemu wanting to use CA is thus answered independently of
whether the fd management solution is solved by libvirt handing an fd for CA
to qemu prior to any monitor command where qemu will then need to use CA, or
whether qemu is taught to asynchronously ask libvirt to open an fd for CA on
qemu's behalf. The answer is that libvirt already tracks whether qemu
should access CA, and just needs a way to enforce that knowledge. The
enforcement already exists for non-NFS via SELinux labels, and the proposal
to add fd handling will expand that enforcement to also cover NFS.
OK. I think fds would be useful internally in a privilege separation
mode in plain QEMU too.