
On 2/19/20 10:40 AM, Peter Krempa wrote:
1b: base.raw probes as qcow2 (because of whatever the guest wrote there), using it as qcow2 is wrong - the guest will see corrupted data. What's more, if the probe sees it as qcow2 with backing file, and we open the backing file, it also has security implications.
We don't open the backing file in the proposed logic. That is specifically forbidden.
I agree that you contained the security risk by not following any file names mentioned in based.raw when interpreted as qcow2, but that does not mean you contained the data corruption risk.
Also in pre-blockdev configurations the same situation would happen as we allowed qemu to probe the backing file despite assuming the format to be raw. This was as we weren't able to tell qemu what the backing format is. This is fixed with -blockdev, so this scenario is exactly the same as it was before.
We assumed it to be raw, the question is whether qemu also assumed it to be raw, or qemu assumed it to be qcow2. If qemu assumed it to be qcow2, sVirt may have saved us from the assumption going haywire and opening forbidden files, but it did NOT save the guest from seeing corrupted data. If qemu assumed it to be raw, then all that was missing pre-blockdev was a way for us to tell qemu its assumptions were correct.
Scenario 2:
base.qcow2 <- wrap.qcow2
where wrap.qcow2 specifies backing of base.qcow2 but not the format. If we probe, we will always have just one outcome:
2a: base.qcow2 probes as qcow2. Using it as qcow2 is correct, but if base.qcow2 has a further backing image, the backing chain is now dependent on a probe.
Since 1b and 2a have the same probe result, but massively different data corruption and/or security concerns, it is NOT sufficient to claim that a probe was safe merely because "the probed image does not have any backing or data file". It is ONLY safe if the probe turns up raw. Any other probed format is inherently unsafe.
I disagree here. If the probe of 'base.qcow2' showed a backing file, we refuse startup right away. If it didn't show any backing file, we continue:
1) with old (pre-blockdev qemus) libvirt starts qemu with wrap.qcow2 as image. Qemu tries to open the backing file and probes it. Now if we've mis-detected that there is a backing file, we will depend on sVirt to save us. This scenario is how all of this was working until 2 months ago. It's because we've asumed that the format of 'base.qcow2' was raw, but started qemu. Since we didn't tell qemu what the format of 'base.qcow2' as it was impossible, we've relied on sVirt anyways.
This is the same as it was before.
So you're arguing that because qemu probes and treats the file as qcow2, even though we had assumed raw, but that the data actually was qcow2 (so the guest did not see data corruption), that we want to continue this practice by explicitly telling qemu that it is qcow2. Then this all boils down to "what does qemu do when it probes an image that does not result in raw". If qemu trusted the probe results anyway, then data corruption was already possible, but once the data corruption happens, the guest can no longer reverse the corruption nor cause further security damage (once qemu treats a previously-raw image as qcow2, the guest can no longer rewrite the qcow2 metadata). If qemu failed to use the image because it treated the image as raw, then libvirt's decision to tell qemu that the image is qcow2 will CAUSE data corruption. I recall that older qemu did blindly trust the probe results, but that there was discussion on the qemu list about patching things to warn about probes that resulted in anything other than raw. But I could not quickly find mailing list discussions or specific patches that mention what actually happens; the closest I got was: commit e4c8f2925d22584b2008aadea5c70e1e05c2a522 Author: Daniel P. Berrangé <berrange@redhat.com> Date: Tue Nov 20 17:56:46 2018 +0000 iotests: fix nbd test 233 to work correctly with raw images The first qemu-io command must honour the $IMGFMT that is set rather than hardcoding qcow2. The qemu-nbd commands should also set $IMGFMT to avoid the insecure format probe warning.
2) with new qemu, we do the same, but start qemu and specifically tell it that "the backing format is qcow2 and that the image has no backing file. That way qemu doesn't even attempt to open anythting. This means that this scenario fixes any deployment without selinux, while keeping old semantics around.
If you tell qemu that something is qcow2, but qemu has ever in the past treated that file as raw, then you are forcing data corruption on the guest, even if you avoid a security issue of chasing further backing files from treating that image as qcow2.
We perform the image format detection and in the case that we were able to probe the format and the format does not specify a backing store (or doesn't support backing store) we can use this format.
Wrong. The condition needs to be:
If we probe the format, and the probe returns raw, then it is safe to use raw as the format.
That doesn't solve anythign then. The idea of this series is to relax the restrictions we've imposed after introducing blockdev to return the main semantics back to what we've allowed in pre-blockdev configurations.
The only way I see that might be safe to relax restrictions is if the filename heuristics give us a clue as to the user's intent. Data corruption is bad enough that we should never be the cause of it. A user with a broken setup deserves a decent error message that their setup is broken, and how to fix it (even so much as "we detected qcow2, but weren't sure if you might have had a raw file instead, so do this to tell us which one you meant"), but blindly picking one always creates a corner case where our choice is wrong.
Namely a user creates an overlay on top of single raw/qcow2 image and expects it to work. And it's not just random users, libguestfs and openstack also neglected to set the backing format.
Yes, and they are getting patched. Belatedly, but better late than never.
The price for this is that libvirt will need to keep the image format detector still current and working or replace it by invocation of qemu-img.
Maybe. Any format that qemu recognizes but libvirt does not risks a case where libvirt probes the image as raw but lets qemu re-probe the image and
That doesn't happen with blockdev. We dont' let qemu probe.
We are just shifting the burden on who causes the data corruption when a probe goes wrong - it used to be qemu, now it is libvirt.
I disagree with the logic here. What we really need is:
If the backing format was not specified, we probe to see what is there. If the result of that probe is raw, it is safe to treat the image as raw. If the result is anything else, we must report an error stating that what we probed could not be trusted unless the user adds an explicit backing format (either confirming that our probe was correct, or with the correct format overriding what we mis-probed).
As noted above, using this logic would be pointless. We are better off just reporting the error always if we also don't allow qcow2 without backing file to be used as it was previously used.
Then report the error always. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org