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 84 uint32_t len;
85 85 } QCowExtension;
86 86 #define QCOW_EXT_MAGIC_END 0
  87 +#define QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
87 88  
88 89  
89 90 typedef struct __attribute__((packed)) QCowSnapshotHeader {
... ... @@ -235,6 +236,24 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
235 236 switch (ext.magic) {
236 237 case QCOW_EXT_MAGIC_END:
237 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 257 default:
239 258 /* unknown magic -- just skip it */
240 259 offset += ((ext.len + 7) & ~7);
... ... @@ -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 1553 int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
  1554 + int backing_format_len = 0;
1533 1555 QCowHeader header;
1534 1556 uint64_t tmp, offset;
1535 1557 QCowCreateState s1, *s = &s1;
  1558 + QCowExtension ext_bf = {0, 0};
  1559 +
1536 1560  
1537 1561 memset(s, 0, sizeof(*s));
1538 1562  
... ... @@ -1546,6 +1570,12 @@ static int qcow_create(const char *filename, int64_t total_size,
1546 1570 header_size = sizeof(header);
1547 1571 backing_filename_len = 0;
1548 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 1579 header.backing_file_offset = cpu_to_be64(header_size);
1550 1580 backing_filename_len = strlen(backing_file);
1551 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 1620 /* write all the data */
1591 1621 write(fd, &header, sizeof(header));
1592 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 1636 write(fd, backing_file, backing_filename_len);
1594 1637 }
1595 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 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 1661 static int qcow_make_empty(BlockDriverState *bs)
1613 1662 {
1614 1663 #if 0
... ... @@ -2685,4 +2734,6 @@ BlockDriver bdrv_qcow2 = {
2685 2734 .bdrv_snapshot_delete = qcow_snapshot_delete,
2686 2735 .bdrv_snapshot_list = qcow_snapshot_list,
2687 2736 .bdrv_get_info = qcow_get_info,
  2737 +
  2738 + .bdrv_create2 = qcow_create2,
2688 2739 };
... ...