]> git.pld-linux.org Git - packages/qemu.git/commitdiff
- from gentoo LINUX_2_6_22
authorElan Ruusamäe <glen@pld-linux.org>
Fri, 23 May 2008 23:20:18 +0000 (23:20 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    qemu-CVE-2008-0928.patch -> 1.1
    qemu-CVE-2008-2004.patch -> 1.1

qemu-CVE-2008-0928.patch [new file with mode: 0644]
qemu-CVE-2008-2004.patch [new file with mode: 0644]

diff --git a/qemu-CVE-2008-0928.patch b/qemu-CVE-2008-0928.patch
new file mode 100644 (file)
index 0000000..ee410d6
--- /dev/null
@@ -0,0 +1,239 @@
+https://bugzilla.redhat.com/show_bug.cgi?id=433560
+
+Revised block device address range patch
+
+The original patch adds checks to the main  bdrv_XXX apis to validate that
+the I/O operation does not exceed the bounds of the disk - ie beyond the
+total_sectors count. This works correctly for bdrv_XXX calls from the IDE
+driver.  With disk formats like QCow though,  bdrv_XXX is re-entrant,
+because the QCow driver uses the block APIs for dealing with its underlying
+file.  The problem is that QCow files are grow-on-demand, so writes will
+*explicitly* be beyond the end of the file. The original patch blocks any
+I/O operation which would cause the QCow file to grow, resulting it more
+or less catasatrophic data loss.
+
+Basically the bounds checking needs to distinguish between checking for
+the logical disk extents, vs the physical disk extents. For raw files
+these are the same so initial tests showed no problems, but for QCow
+format disks they are different & thus we see a problem
+
+What follows is a revised patch which introduces a flag BDRV_O_AUTOGROW
+which can be passed to bdrv_open to indicate that the files can be allowed
+to automatically extend their extents. This flag should only be used by
+internal block drivers such as block-qcow2.c, block-vmdk.c  In my testing
+this has fixed the qcow corruption, and still maintains the goal of Ian's
+original patch which was to prevent the guest VM writing beyond the logical
+disk extents.
+
+diff -rup kvm-60.orig/qemu/block.c kvm-60.new/qemu/block.c
+--- kvm-60.orig/qemu/block.c   2008-02-26 18:44:28.000000000 -0500
++++ kvm-60.new/qemu/block.c    2008-02-26 18:44:52.000000000 -0500
+@@ -124,6 +124,60 @@ void path_combine(char *dest, int dest_s
+     }
+ }
++static int bdrv_rd_badreq_sectors(BlockDriverState *bs,
++                                  int64_t sector_num, int nb_sectors)
++{
++    return
++        nb_sectors < 0 ||
++        sector_num < 0 ||
++        nb_sectors > bs->total_sectors ||
++        sector_num > bs->total_sectors - nb_sectors;
++}
++
++static int bdrv_rd_badreq_bytes(BlockDriverState *bs,
++                                int64_t offset, int count)
++{
++    int64_t size = bs->total_sectors << SECTOR_BITS;
++    return
++        count < 0 ||
++        size < 0 ||
++        count > size ||
++        offset > size - count;
++}
++
++static int bdrv_wr_badreq_sectors(BlockDriverState *bs,
++                                  int64_t sector_num, int nb_sectors)
++{
++    if (sector_num < 0 ||
++        nb_sectors < 0)
++        return 1;
++
++    if (sector_num > bs->total_sectors - nb_sectors) {
++        if (bs->autogrow)
++            bs->total_sectors = sector_num + nb_sectors;
++        else
++            return 1;
++    }
++    return 0;
++}
++
++static int bdrv_wr_badreq_bytes(BlockDriverState *bs,
++                                int64_t offset, int count)
++{
++    int64_t size = bs->total_sectors << SECTOR_BITS;
++    if (count < 0 ||
++        offset < 0)
++        return 1;
++
++    if (offset > size - count) {
++        if (bs->autogrow)
++            bs->total_sectors = (offset + count + SECTOR_SIZE - 1) >> SECTOR_BITS;
++        else
++            return 1;
++    }
++    return 0;
++}
++
+ static void bdrv_register(BlockDriver *bdrv)
+ {
+@@ -332,6 +386,10 @@ int bdrv_open2(BlockDriverState *bs, con
+     bs->read_only = 0;
+     bs->is_temporary = 0;
+     bs->encrypted = 0;
++    bs->autogrow = 0;
++
++    if (flags & BDRV_O_AUTOGROW)
++        bs->autogrow = 1;
+     if (flags & BDRV_O_SNAPSHOT) {
+         BlockDriverState *bs1;
+@@ -376,6 +434,7 @@ int bdrv_open2(BlockDriverState *bs, con
+     }
+     bs->drv = drv;
+     bs->opaque = qemu_mallocz(drv->instance_size);
++    bs->total_sectors = 0; /* driver will set if it does not do getlength */
+     if (bs->opaque == NULL && drv->instance_size > 0)
+         return -1;
+     /* Note: for compatibility, we open disk image files as RDWR, and
+@@ -441,6 +500,7 @@ void bdrv_close(BlockDriverState *bs)
+         bs->drv = NULL;
+         /* call the change callback */
++        bs->total_sectors = 0;
+         bs->media_changed = 1;
+         if (bs->change_cb)
+             bs->change_cb(bs->change_opaque);
+@@ -506,6 +566,8 @@ int bdrv_read(BlockDriverState *bs, int6
+     if (!drv)
+         return -ENOMEDIUM;
++    if (bdrv_rd_badreq_sectors(bs, sector_num, nb_sectors))
++        return -EDOM;
+     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+             memcpy(buf, bs->boot_sector_data, 512);
+         sector_num++;
+@@ -546,6 +608,8 @@ int bdrv_write(BlockDriverState *bs, int
+         return -ENOMEDIUM;
+     if (bs->read_only)
+         return -EACCES;
++    if (bdrv_wr_badreq_sectors(bs, sector_num, nb_sectors))
++        return -EDOM;
+     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+         memcpy(bs->boot_sector_data, buf, 512);
+     }
+@@ -671,6 +735,8 @@ int bdrv_pread(BlockDriverState *bs, int
+         return -ENOMEDIUM;
+     if (!drv->bdrv_pread)
+         return bdrv_pread_em(bs, offset, buf1, count1);
++    if (bdrv_rd_badreq_bytes(bs, offset, count1))
++        return -EDOM;
+     return drv->bdrv_pread(bs, offset, buf1, count1);
+ }
+@@ -686,6 +752,8 @@ int bdrv_pwrite(BlockDriverState *bs, in
+         return -ENOMEDIUM;
+     if (!drv->bdrv_pwrite)
+         return bdrv_pwrite_em(bs, offset, buf1, count1);
++    if (bdrv_wr_badreq_bytes(bs, offset, count1))
++        return -EDOM;
+     return drv->bdrv_pwrite(bs, offset, buf1, count1);
+ }
+@@ -1091,6 +1159,8 @@ int bdrv_write_compressed(BlockDriverSta
+         return -ENOMEDIUM;
+     if (!drv->bdrv_write_compressed)
+         return -ENOTSUP;
++    if (bdrv_wr_badreq_sectors(bs, sector_num, nb_sectors))
++        return -EDOM;
+     return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
+ }
+@@ -1237,6 +1307,8 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDri
+     if (!drv)
+         return NULL;
++    if (bdrv_rd_badreq_sectors(bs, sector_num, nb_sectors))
++        return NULL;
+     /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
+     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+@@ -1268,6 +1340,8 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDr
+         return NULL;
+     if (bs->read_only)
+         return NULL;
++    if (bdrv_wr_badreq_sectors(bs, sector_num, nb_sectors))
++        return NULL;
+     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+         memcpy(bs->boot_sector_data, buf, 512);
+     }
+diff -rup kvm-60.orig/qemu/block.h kvm-60.new/qemu/block.h
+--- kvm-60.orig/qemu/block.h   2008-01-20 07:35:04.000000000 -0500
++++ kvm-60.new/qemu/block.h    2008-02-26 18:44:52.000000000 -0500
+@@ -45,6 +45,7 @@ typedef struct QEMUSnapshotInfo {
+                                      it (default for
+                                      bdrv_file_open()) */
+ #define BDRV_O_DIRECT      0x0020
++#define BDRV_O_AUTOGROW    0x0040 /* Allow backing file to extend when writing past end of file */
+ #ifndef QEMU_IMG
+ void bdrv_info(void);
+diff -rup kvm-60.orig/qemu/block_int.h kvm-60.new/qemu/block_int.h
+--- kvm-60.orig/qemu/block_int.h       2008-01-20 07:35:04.000000000 -0500
++++ kvm-60.new/qemu/block_int.h        2008-02-26 18:44:52.000000000 -0500
+@@ -97,6 +97,7 @@ struct BlockDriverState {
+     int locked;    /* if true, the media cannot temporarily be ejected */
+     int encrypted; /* if true, the media is encrypted */
+     int sg;        /* if true, the device is a /dev/sg* */
++    int autogrow;  /* if true, the backing store can auto-extend to allocate new extents */
+     /* event callback when inserting/removing */
+     void (*change_cb)(void *opaque);
+     void *change_opaque;
+diff -rup kvm-60.orig/qemu/block-qcow2.c kvm-60.new/qemu/block-qcow2.c
+--- kvm-60.orig/qemu/block-qcow2.c     2008-01-20 07:35:04.000000000 -0500
++++ kvm-60.new/qemu/block-qcow2.c      2008-02-26 18:44:52.000000000 -0500
+@@ -191,7 +191,7 @@ static int qcow_open(BlockDriverState *b
+     int len, i, shift, ret;
+     QCowHeader header;
+-    ret = bdrv_file_open(&s->hd, filename, flags);
++    ret = bdrv_file_open(&s->hd, filename, flags | BDRV_O_AUTOGROW);
+     if (ret < 0)
+         return ret;
+     if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
+diff -rup kvm-60.orig/qemu/block-qcow.c kvm-60.new/qemu/block-qcow.c
+--- kvm-60.orig/qemu/block-qcow.c      2008-01-20 07:35:04.000000000 -0500
++++ kvm-60.new/qemu/block-qcow.c       2008-02-26 18:44:52.000000000 -0500
+@@ -95,7 +95,7 @@ static int qcow_open(BlockDriverState *b
+     int len, i, shift, ret;
+     QCowHeader header;
+-    ret = bdrv_file_open(&s->hd, filename, flags);
++    ret = bdrv_file_open(&s->hd, filename, flags | BDRV_O_AUTOGROW);
+     if (ret < 0)
+         return ret;
+     if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
+diff -rup kvm-60.orig/qemu/block-vmdk.c kvm-60.new/qemu/block-vmdk.c
+--- kvm-60.orig/qemu/block-vmdk.c      2008-01-20 07:35:04.000000000 -0500
++++ kvm-60.new/qemu/block-vmdk.c       2008-02-26 18:44:52.000000000 -0500
+@@ -375,7 +375,7 @@ static int vmdk_open(BlockDriverState *b
+         flags = BDRV_O_RDONLY;
+     fprintf(stderr, "(VMDK) image open: flags=0x%x filename=%s\n", flags, bs->filename);
+-    ret = bdrv_file_open(&s->hd, filename, flags);
++    ret = bdrv_file_open(&s->hd, filename, flags | BDRV_O_AUTOGROW);
+     if (ret < 0)
+         return ret;
+     if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
diff --git a/qemu-CVE-2008-2004.patch b/qemu-CVE-2008-2004.patch
new file mode 100644 (file)
index 0000000..c30a54d
--- /dev/null
@@ -0,0 +1,55 @@
+--- vl.c       2008-01-06 14:38:42.000000000 -0500
++++ vl.c       2008-05-13 09:56:45.000000000 -0400
+@@ -4877,13 +4877,14 @@
+     int bus_id, unit_id;
+     int cyls, heads, secs, translation;
+     BlockDriverState *bdrv;
++    BlockDriver *drv = NULL;
+     int max_devs;
+     int index;
+     int cache;
+     int bdrv_flags;
+     char *params[] = { "bus", "unit", "if", "index", "cyls", "heads",
+                        "secs", "trans", "media", "snapshot", "file",
+-                       "cache", NULL };
++                     "cache", "format", NULL };
+     if (check_params(buf, sizeof(buf), params, str) < 0) {
+          fprintf(stderr, "qemu: unknowm parameter '%s' in '%s'\n",
+@@ -5051,6 +5052,14 @@
+         }
+     }
++    if (get_param_value(buf, sizeof(buf), "format", str)) {
++       drv = bdrv_find_format(buf);
++       if (!drv) {
++          fprintf(stderr, "qemu: '%s' invalid format\n", buf);
++          return -1;
++         }
++    }
++
+     get_param_value(file, sizeof(file), "file", str);
+     /* compute bus and unit according index */
+@@ -5150,7 +5159,7 @@
+         bdrv_flags |= BDRV_O_SNAPSHOT;
+     if (!cache)
+         bdrv_flags |= BDRV_O_DIRECT;
+-    if (bdrv_open(bdrv, file, bdrv_flags) < 0 || qemu_key_check(bdrv, file)) {
++    if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0 || qemu_key_check(bdrv, file)) {
+         fprintf(stderr, "qemu: could not open disk image %s\n",
+                         file);
+         return -1;
+--- qemu-doc.texi      2008-01-06 14:38:42.000000000 -0500
++++ qemu-doc.texi      2008-05-13 09:57:57.000000000 -0400
+@@ -252,6 +252,10 @@
+ @var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}).
+ @item cache=@var{cache}
+ @var{cache} is "on" or "off" and allows to disable host cache to access data.
++@item format=@var{format}
++Specify which disk @var{format} will be used rather than detecting
++the format.  Can be used to specifiy format=raw to avoid interpreting
++an untrusted format header.
+ @end table
+ Instead of @option{-cdrom} you can use:
This page took 0.047151 seconds and 4 git commands to generate.