]> xenbits.xensource.com Git - qemu-xen-4.1-testing.git/commitdiff
Fix COW extendability for vulnerability fix.
authorIan Jackson <iwj@mariner.uk.xensource.com>
Fri, 23 May 2008 17:43:27 +0000 (18:43 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Fri, 23 May 2008 17:43:27 +0000 (18:43 +0100)
(Thanks to report from Daniel Berrange.
 Corresponds to my email to xen-devel of 2008-02-27
 Subject: Re: [Xen-devel] [PATCH] ioemu block device extent checks.)

block-qcow.c
block-qcow2.c
block-raw-posix.c
block-raw-win32.c
block-vmdk.c
block.c
block.h
block_int.h

index 0ac2b42b4fdf0b30a7a4e60ac2cf48a77a1bbe12..63daaad3eca79a1a93ad447efdabd0fecccf7960 100644 (file)
@@ -95,7 +95,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     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_EXTENDABLE);
     if (ret < 0)
         return ret;
     if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
index 577210b21acb6248443c88c1ad24141f83dcf3a9..eebc260321ffdb6289d68919cb491476692fe261 100644 (file)
@@ -191,7 +191,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     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_EXTENDABLE);
     if (ret < 0)
         return ret;
     if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
index 6b0009e564ea9c61191258c6965e20cb5de3aa80..050683624ae1a0285f8f6b8b92e94d16c5115a3b 100644 (file)
@@ -923,4 +923,6 @@ BlockDriver bdrv_host_device = {
     .bdrv_set_locked = raw_set_locked,
     /* generic scsi device */
     .bdrv_ioctl = raw_ioctl,
+
+    .bdrv_flags = BLOCK_DRIVER_FLAG_EXTENDABLE
 };
index 43d3f6c4c216d6eb2f7286bbc74acc96d35decd7..77d1936b863b5e98e7648e162baa58cc310bb04d 100644 (file)
@@ -545,4 +545,6 @@ BlockDriver bdrv_host_device = {
     .bdrv_pread = raw_pread,
     .bdrv_pwrite = raw_pwrite,
     .bdrv_getlength = raw_getlength,
+
+    .bdrv_flags = BLOCK_DRIVER_FLAG_EXTENDABLE;
 };
index 9b5fb7346a9f932cddfd194c15032ffb47a02063..e70dae30e50486d3b7c27098137195a51fd01c54 100644 (file)
@@ -378,7 +378,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
         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_EXTENDABLE);
     if (ret < 0)
         return ret;
     if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
diff --git a/block.c b/block.c
index 72003d3125570b1dab3c19a3c4dad4456dffdc1e..8932ff845517e64cdcc5aff44ff73ce387f0fcfc 100644 (file)
--- a/block.c
+++ b/block.c
@@ -126,20 +126,23 @@ void path_combine(char *dest, int dest_size,
 static int bdrv_rw_badreq_sectors(BlockDriverState *bs,
                                int64_t sector_num, int nb_sectors)
 {
-    return
+    return (
        nb_sectors < 0 ||
        nb_sectors > bs->total_sectors ||
-       sector_num > bs->total_sectors - nb_sectors;
+       sector_num > bs->total_sectors - nb_sectors
+       ) && !bs->extendable;
 }
 
 static int bdrv_rw_badreq_bytes(BlockDriverState *bs,
                                  int64_t offset, int count)
 {
     int64_t size = bs->total_sectors << SECTOR_BITS;
-    return
+    return (
        count < 0 ||
        count > size ||
-       offset > size - count;
+       offset > size - count
+       ) && !bs->extendable;
+    
 }
 
 static void bdrv_register(BlockDriver *bdrv)
@@ -354,6 +357,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     bs->is_temporary = 0;
     bs->encrypted = 0;
 
+    if (flags & BDRV_O_EXTENDABLE) {
+       if (!(drv->bdrv_flags & BLOCK_DRIVER_FLAG_EXTENDABLE))
+           return -ENOSYS;
+       bs->extendable = 1;
+    }
+
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
         int64_t total_size;
diff --git a/block.h b/block.h
index b73050556abe3761c68e852d9bf425ba8e977de9..7a98f2dc8ab549a247275808c71f711d8586b761 100644 (file)
--- a/block.h
+++ b/block.h
@@ -45,6 +45,8 @@ typedef struct QEMUSnapshotInfo {
                                      it (default for
                                      bdrv_file_open()) */
 #define BDRV_O_DIRECT      0x0020
+#define BDRV_O_EXTENDABLE  0x0080 /* allow writes out of original size range;
+                                    only effective for some drivers */
 
 #ifndef QEMU_IMG
 void bdrv_info(void);
index 137000e14075fb2b1b2d55739a8a83a27c510e22..d635e247ceec82ce2e7dc1b16d457eee1ffbfd1b 100644 (file)
@@ -30,6 +30,8 @@
 #define BLOCK_FLAG_COMPRESS    2
 #define BLOCK_FLAG_COMPAT6     4
 
+#define BLOCK_DRIVER_FLAG_EXTENDABLE  0x0001u
+
 struct BlockDriver {
     const char *format_name;
     int instance_size;
@@ -85,6 +87,7 @@ struct BlockDriver {
     /* to control generic scsi devices */
     int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
 
+    unsigned bdrv_flags;
     BlockDriverAIOCB *free_aiocb;
     struct BlockDriver *next;
 };
@@ -97,6 +100,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 extendable;/* if true, we may write out of original range */
     /* event callback when inserting/removing */
     void (*change_cb)(void *opaque);
     void *change_opaque;