From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53287) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VsiT7-0001Qg-1S for qemu-devel@nongnu.org; Mon, 16 Dec 2013 19:25:05 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VsiT2-0005Bg-4T for qemu-devel@nongnu.org; Mon, 16 Dec 2013 19:25:00 -0500 Received: from mx1.redhat.com ([209.132.183.28]:47190) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VsiT1-0005Bc-T0 for qemu-devel@nongnu.org; Mon, 16 Dec 2013 19:24:56 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rBH0OtVp011702 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 16 Dec 2013 19:24:55 -0500 Message-ID: <52AF99D5.4050800@redhat.com> Date: Mon, 16 Dec 2013 17:24:53 -0700 From: Eric Blake MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="wRmldka6VXApO1DNmK7u7wvf1sDXBvpAv" Subject: [Qemu-devel] hindsight on qcow2v3 format List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "qemu-devel@nongnu.org" , "libvir-list@redhat.com" This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --wRmldka6VXApO1DNmK7u7wvf1sDXBvpAv Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable I spent a couple hours today debugging a bug in an older branch of libvirt (0.10.2) - one where libvirt only knew how to parse version 2 qcow2 images. Alas, that version of libvirt can be coerced into reading the header of a random file under the assumption that it is qcow2 data, and where it tries to find the backing format information in the header extensions without first validating that the file format actually matches qcow2 (that is, it looks for header extensions starting at offset 72 without first checking the version field (bytes 4-7) contains 2= ). So far, we've been lucky: since libvirt is trying to parse 72-75 as a version 2 extension header magic number, and the number is stored in big endian format, we end up reading the first 4 bytes of the version 3 incompatible_features field, which so far are always 0 (we don't have that many incompatible features yet), and that happens to be the magic number for end of extension headers; and thus libvirt quit trying to look for any further extension headers. Furthermore, since libvirt already refuses to probe backing file format unless explicitly allowed by user action (since mis-probing a raw file is CVE-worthy if done automatically), the damage stopped there, and the worst I could do (without intentionally bypassing the CVE safety valve) was fail a test in the libvirt testsuite when using version 3 files. But it DOES mean that libvirt fails to find the backing header format extension of a v3 file, even when one is present, because libvirt fails to start looking at the right offset. But it does raise a question: What happens if we eventually DO reach bit 32, so that bytes 72-75 is no longer all 0s and therefore no longer the end-of-extension marker? It might be possible to write a file that has one interpretation as a valid qcow2v3, while having a different interpretation by the older libvirt, such that libvirt tries to treat a backing file as an incorrect format if it is probing. Is it worth tweaking docs/specs/qcow2.txt to permanently change the incompatible_features field to be 4 bytes (76-79) and mandate that bytes 72-75 always be 0, as a conservative way to prevent other misbehavior of programs like libvirt 0.10.2 that have code paths that don't correctly validate for version 2 files? And if we ever really did hit a situation of having 31 or more incompatible features, I could envision using bit 31 as an incompatible_feature witness that tells new enough qemu to look at some other offset for remaining feature bits (thankfully, the semantics of the incompatible_feature field mean that older qemu that honors version 3 formats will reject a file with incompatible_feature bit 31 set), so this is no real loss in the number of potential incompatible features being added. If we had a time machine, I would suggest that we change 72-75 to have constant contents as a new magic number, and 76-79 encode the length of the remaining header, and delay the location of incompatible_features into the remaining header; such that this situation of libvirt looking for extensions would still find known could have still found the backing file format extension header. But that ship has sailed - all we can do now is decide to encode 72-75 as permanent 0s. --=20 Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org --wRmldka6VXApO1DNmK7u7wvf1sDXBvpAv Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) Comment: Public key at http://people.redhat.com/eblake/eblake.gpg Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBCAAGBQJSr5nVAAoJEKeha0olJ0NqstcH+waXMLll/FNc1c4K8WmBBIH9 XGXNS1b3bGHOU5IQVLXABUn7e0XztJP+9cz20UwQGIdQcc1PuGtkzS4JXuX8xhSv nh6vTumi087b7y2l7+47qAsHOs/A3mpqUhaSva0ddwyPjZoeRdRqXu8VGMUf6XJ7 D060p+9tpx/Wo3MGLuGUkXCbtO4ie10EYfcVI8Io7QB0wCQLbE9g7Ni5Jmd11N9G ds5D/iv6NbKPMYTpwn7Q7I3pJTWdQBW36pivCIgpePWXudz9VipFCdzlvCEWONk4 l4RHnBDMXMMDIGJ1wRGDztldX0gQT/FMvJhb5iWg2uAN57xeYF+DAW+jHPJPF3c= =a7QX -----END PGP SIGNATURE----- --wRmldka6VXApO1DNmK7u7wvf1sDXBvpAv--