Commit f965509c9ee8635c66dbf4342a9c67c222951bc3

Authored by aliguori
1 parent 5eb45639

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 <uril@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6909 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 53 additions and 2 deletions
block-qcow2.c
@@ -84,6 +84,7 @@ typedef struct { @@ -84,6 +84,7 @@ typedef struct {
84 uint32_t len; 84 uint32_t len;
85 } QCowExtension; 85 } QCowExtension;
86 #define QCOW_EXT_MAGIC_END 0 86 #define QCOW_EXT_MAGIC_END 0
  87 +#define QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
87 88
88 89
89 typedef struct __attribute__((packed)) QCowSnapshotHeader { 90 typedef struct __attribute__((packed)) QCowSnapshotHeader {
@@ -235,6 +236,24 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset, @@ -235,6 +236,24 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
235 switch (ext.magic) { 236 switch (ext.magic) {
236 case QCOW_EXT_MAGIC_END: 237 case QCOW_EXT_MAGIC_END:
237 return 0; 238 return 0;
  239 +
  240 + case QCOW_EXT_MAGIC_BACKING_FORMAT:
  241 + if (ext.len >= sizeof(bs->backing_format)) {
  242 + fprintf(stderr, "ERROR: ext_backing_format: len=%u too large"
  243 + " (>=%lu)\n",
  244 + ext.len, sizeof(bs->backing_format));
  245 + return 2;
  246 + }
  247 + if (bdrv_pread(s->hd, offset , bs->backing_format,
  248 + ext.len) != ext.len)
  249 + return 3;
  250 + bs->backing_format[ext.len] = '\0';
  251 +#ifdef DEBUG_EXT
  252 + printf("Qcow2: Got format extension %s\n", bs->backing_format);
  253 +#endif
  254 + offset += ((ext.len + 7) & ~7);
  255 + break;
  256 +
238 default: 257 default:
239 /* unknown magic -- just skip it */ 258 /* unknown magic -- just skip it */
240 offset += ((ext.len + 7) & ~7); 259 offset += ((ext.len + 7) & ~7);
@@ -1526,13 +1545,18 @@ static void create_refcount_update(QCowCreateState *s, @@ -1526,13 +1545,18 @@ static void create_refcount_update(QCowCreateState *s,
1526 } 1545 }
1527 } 1546 }
1528 1547
1529 -static int qcow_create(const char *filename, int64_t total_size,  
1530 - const char *backing_file, int flags) 1548 +static int qcow_create2(const char *filename, int64_t total_size,
  1549 + const char *backing_file, const char *backing_format,
  1550 + int flags)
1531 { 1551 {
  1552 +
1532 int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; 1553 int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
  1554 + int backing_format_len = 0;
1533 QCowHeader header; 1555 QCowHeader header;
1534 uint64_t tmp, offset; 1556 uint64_t tmp, offset;
1535 QCowCreateState s1, *s = &s1; 1557 QCowCreateState s1, *s = &s1;
  1558 + QCowExtension ext_bf = {0, 0};
  1559 +
1536 1560
1537 memset(s, 0, sizeof(*s)); 1561 memset(s, 0, sizeof(*s));
1538 1562
@@ -1546,6 +1570,12 @@ static int qcow_create(const char *filename, int64_t total_size, @@ -1546,6 +1570,12 @@ static int qcow_create(const char *filename, int64_t total_size,
1546 header_size = sizeof(header); 1570 header_size = sizeof(header);
1547 backing_filename_len = 0; 1571 backing_filename_len = 0;
1548 if (backing_file) { 1572 if (backing_file) {
  1573 + if (backing_format) {
  1574 + ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT;
  1575 + backing_format_len = strlen(backing_format);
  1576 + ext_bf.len = (backing_format_len + 7) & ~7;
  1577 + header_size += ((sizeof(ext_bf) + ext_bf.len + 7) & ~7);
  1578 + }
1549 header.backing_file_offset = cpu_to_be64(header_size); 1579 header.backing_file_offset = cpu_to_be64(header_size);
1550 backing_filename_len = strlen(backing_file); 1580 backing_filename_len = strlen(backing_file);
1551 header.backing_file_size = cpu_to_be32(backing_filename_len); 1581 header.backing_file_size = cpu_to_be32(backing_filename_len);
@@ -1590,6 +1620,19 @@ static int qcow_create(const char *filename, int64_t total_size, @@ -1590,6 +1620,19 @@ static int qcow_create(const char *filename, int64_t total_size,
1590 /* write all the data */ 1620 /* write all the data */
1591 write(fd, &header, sizeof(header)); 1621 write(fd, &header, sizeof(header));
1592 if (backing_file) { 1622 if (backing_file) {
  1623 + if (backing_format_len) {
  1624 + char zero[16];
  1625 + int d = ext_bf.len - backing_format_len;
  1626 +
  1627 + memset(zero, 0, sizeof(zero));
  1628 + cpu_to_be32s(&ext_bf.magic);
  1629 + cpu_to_be32s(&ext_bf.len);
  1630 + write(fd, &ext_bf, sizeof(ext_bf));
  1631 + write(fd, backing_format, backing_format_len);
  1632 + if (d>0) {
  1633 + write(fd, zero, d);
  1634 + }
  1635 + }
1593 write(fd, backing_file, backing_filename_len); 1636 write(fd, backing_file, backing_filename_len);
1594 } 1637 }
1595 lseek(fd, s->l1_table_offset, SEEK_SET); 1638 lseek(fd, s->l1_table_offset, SEEK_SET);
@@ -1609,6 +1652,12 @@ static int qcow_create(const char *filename, int64_t total_size, @@ -1609,6 +1652,12 @@ static int qcow_create(const char *filename, int64_t total_size,
1609 return 0; 1652 return 0;
1610 } 1653 }
1611 1654
  1655 +static int qcow_create(const char *filename, int64_t total_size,
  1656 + const char *backing_file, int flags)
  1657 +{
  1658 + return qcow_create2(filename, total_size, backing_file, NULL, flags);
  1659 +}
  1660 +
1612 static int qcow_make_empty(BlockDriverState *bs) 1661 static int qcow_make_empty(BlockDriverState *bs)
1613 { 1662 {
1614 #if 0 1663 #if 0
@@ -2685,4 +2734,6 @@ BlockDriver bdrv_qcow2 = { @@ -2685,4 +2734,6 @@ BlockDriver bdrv_qcow2 = {
2685 .bdrv_snapshot_delete = qcow_snapshot_delete, 2734 .bdrv_snapshot_delete = qcow_snapshot_delete,
2686 .bdrv_snapshot_list = qcow_snapshot_list, 2735 .bdrv_snapshot_list = qcow_snapshot_list,
2687 .bdrv_get_info = qcow_get_info, 2736 .bdrv_get_info = qcow_get_info,
  2737 +
  2738 + .bdrv_create2 = qcow_create2,
2688 }; 2739 };