[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 03/14] block-qcow2: keep backing file format in a qc
From: |
Uri Lublin |
Subject: |
[Qemu-devel] [PATCH 03/14] block-qcow2: keep backing file format in a qcow2 extension |
Date: |
Tue, 17 Mar 2009 22:40:41 +0200 |
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 <address@hidden>
---
block-qcow2.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/block-qcow2.c b/block-qcow2.c
index 23e66b0..8a910fa 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -84,6 +84,7 @@ typedef struct {
uint32_t len;
} QCowExtension;
#define QCOW_EXT_MAGIC_END 0
+#define QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
typedef struct __attribute__((packed)) QCowSnapshotHeader {
@@ -234,6 +235,24 @@ static int qcow_read_extensions(BlockDriverState *bs,
uint64_t start_offset,
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);
@@ -1525,13 +1544,18 @@ static void create_refcount_update(QCowCreateState *s,
}
}
-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));
@@ -1545,6 +1569,12 @@ static int qcow_create(const char *filename, int64_t
total_size,
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);
@@ -1589,6 +1619,19 @@ static int qcow_create(const char *filename, int64_t
total_size,
/* 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);
@@ -1608,6 +1651,12 @@ static int qcow_create(const char *filename, int64_t
total_size,
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
@@ -2684,4 +2733,6 @@ BlockDriver bdrv_qcow2 = {
.bdrv_snapshot_delete = qcow_snapshot_delete,
.bdrv_snapshot_list = qcow_snapshot_list,
.bdrv_get_info = qcow_get_info,
+
+ .bdrv_create2 = qcow_create2,
};
--
1.6.0.6
- [Qemu-devel] [PATCH 00/14] block (mostly qcow2) changes (v6), Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 01/14] Introducing qcow2 extensions, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 02/14] block: support known backing format for image create and open, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 03/14] block-qcow2: keep backing file format in a qcow2 extension,
Uri Lublin <=
- [Qemu-devel] [PATCH 04/14] qemu-img: adding a "-F base_fmt" option to "qemu-img create -b", Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 05/14] block-qcow2: keep highest allocated offset, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 06/14] block-qcow2: export highest-alloc through BlockDriverInfo and get_info(), Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 07/14] block: info blockstats: show highest_allocated if exists, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 08/14] Add a bdrv_close_all() and call it at the end of main(), Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 09/14] block-qcow2: keep highest alloc offset in a qcow2 extension, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 10/14] qemu-img: info: show highest_alloc if exists, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 11/14] qcow2: qcow_read_extensions: make "advance offset over extension" common, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 12/14] block: pass BDRV_BACKING flag to open of a backing file, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 13/14] block: keep flags an image was opened with, Uri Lublin, 2009/03/17