From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LnckY-0007Ww-UM for qemu-devel@nongnu.org; Sat, 28 Mar 2009 13:55:19 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LnckW-0007Un-HA for qemu-devel@nongnu.org; Sat, 28 Mar 2009 13:55:16 -0400 Received: from [199.232.76.173] (port=39379 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LnckW-0007US-8N for qemu-devel@nongnu.org; Sat, 28 Mar 2009 13:55:16 -0400 Received: from savannah.gnu.org ([199.232.41.3]:34365 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LnckV-0001gi-Q7 for qemu-devel@nongnu.org; Sat, 28 Mar 2009 13:55:15 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1LnckV-0001Ab-7k for qemu-devel@nongnu.org; Sat, 28 Mar 2009 17:55:15 +0000 Received: from aliguori by cvs.savannah.gnu.org with local (Exim 4.69) (envelope-from ) id 1LnckU-0001AR-Up for qemu-devel@nongnu.org; Sat, 28 Mar 2009 17:55:15 +0000 MIME-Version: 1.0 Errors-To: aliguori Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Anthony Liguori Message-Id: Date: Sat, 28 Mar 2009 17:55:14 +0000 Subject: [Qemu-devel] [6909] block-qcow2: keep backing file format in a qcow2 extension ( Uri Lublin) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 6909 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6909 Author: aliguori Date: 2009-03-28 17:55:14 +0000 (Sat, 28 Mar 2009) Log Message: ----------- block-qcow2: keep backing file format in a qcow2 extension (Uri Lublin) Use a qcow2 extension to keep the backing file format. By keeping the backing file format, we can: 1. Provide a way to know the backing file format without probing it (setting the format at creation time). 2. Enable using qcow2 format over host block devices. (only if the user specifically asks for it, by providing the format at creation time). Also fixes a security flaw found by Daniel P. Berrange on [1] which summarizes: "Autoprobing: just say no." [1] http://lists.gnu.org/archive/html/qemu-devel/2008-12/msg01083.html Signed-off-by: Uri Lublin Signed-off-by: Anthony Liguori Modified Paths: -------------- trunk/block-qcow2.c Modified: trunk/block-qcow2.c =================================================================== --- trunk/block-qcow2.c 2009-03-28 17:55:10 UTC (rev 6908) +++ trunk/block-qcow2.c 2009-03-28 17:55:14 UTC (rev 6909) @@ -84,6 +84,7 @@ uint32_t len; } QCowExtension; #define QCOW_EXT_MAGIC_END 0 +#define QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA typedef struct __attribute__((packed)) QCowSnapshotHeader { @@ -235,6 +236,24 @@ switch (ext.magic) { case QCOW_EXT_MAGIC_END: return 0; + + case QCOW_EXT_MAGIC_BACKING_FORMAT: + if (ext.len >= sizeof(bs->backing_format)) { + fprintf(stderr, "ERROR: ext_backing_format: len=%u too large" + " (>=%lu)\n", + ext.len, sizeof(bs->backing_format)); + return 2; + } + if (bdrv_pread(s->hd, offset , bs->backing_format, + ext.len) != ext.len) + return 3; + bs->backing_format[ext.len] = '\0'; +#ifdef DEBUG_EXT + printf("Qcow2: Got format extension %s\n", bs->backing_format); +#endif + offset += ((ext.len + 7) & ~7); + break; + default: /* unknown magic -- just skip it */ offset += ((ext.len + 7) & ~7); @@ -1526,14 +1545,19 @@ } } -static int qcow_create(const char *filename, int64_t total_size, - const char *backing_file, int flags) +static int qcow_create2(const char *filename, int64_t total_size, + const char *backing_file, const char *backing_format, + int flags) { + int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; + int backing_format_len = 0; QCowHeader header; uint64_t tmp, offset; QCowCreateState s1, *s = &s1; + QCowExtension ext_bf = {0, 0}; + memset(s, 0, sizeof(*s)); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); @@ -1546,6 +1570,12 @@ header_size = sizeof(header); backing_filename_len = 0; if (backing_file) { + if (backing_format) { + ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT; + backing_format_len = strlen(backing_format); + ext_bf.len = (backing_format_len + 7) & ~7; + header_size += ((sizeof(ext_bf) + ext_bf.len + 7) & ~7); + } header.backing_file_offset = cpu_to_be64(header_size); backing_filename_len = strlen(backing_file); header.backing_file_size = cpu_to_be32(backing_filename_len); @@ -1590,6 +1620,19 @@ /* write all the data */ write(fd, &header, sizeof(header)); if (backing_file) { + if (backing_format_len) { + char zero[16]; + int d = ext_bf.len - backing_format_len; + + memset(zero, 0, sizeof(zero)); + cpu_to_be32s(&ext_bf.magic); + cpu_to_be32s(&ext_bf.len); + write(fd, &ext_bf, sizeof(ext_bf)); + write(fd, backing_format, backing_format_len); + if (d>0) { + write(fd, zero, d); + } + } write(fd, backing_file, backing_filename_len); } lseek(fd, s->l1_table_offset, SEEK_SET); @@ -1609,6 +1652,12 @@ return 0; } +static int qcow_create(const char *filename, int64_t total_size, + const char *backing_file, int flags) +{ + return qcow_create2(filename, total_size, backing_file, NULL, flags); +} + static int qcow_make_empty(BlockDriverState *bs) { #if 0 @@ -2685,4 +2734,6 @@ .bdrv_snapshot_delete = qcow_snapshot_delete, .bdrv_snapshot_list = qcow_snapshot_list, .bdrv_get_info = qcow_get_info, + + .bdrv_create2 = qcow_create2, };