diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/qcow2.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/block/qcow2.c b/block/qcow2.c index 10eccf91e1..7809f5cab4 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -460,6 +460,18 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, s->qcow_version = header.version; + /* Initialise cluster size */ + if (header.cluster_bits < MIN_CLUSTER_BITS || + header.cluster_bits > MAX_CLUSTER_BITS) { + error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits); + ret = -EINVAL; + goto fail; + } + + s->cluster_bits = header.cluster_bits; + s->cluster_size = 1 << s->cluster_bits; + s->cluster_sectors = 1 << (s->cluster_bits - 9); + /* Initialise version 3 header fields */ if (header.version == 2) { header.incompatible_features = 0; @@ -473,6 +485,18 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, be64_to_cpus(&header.autoclear_features); be32_to_cpus(&header.refcount_order); be32_to_cpus(&header.header_length); + + if (header.header_length < 104) { + error_setg(errp, "qcow2 header too short"); + ret = -EINVAL; + goto fail; + } + } + + if (header.header_length > s->cluster_size) { + error_setg(errp, "qcow2 header exceeds cluster size"); + ret = -EINVAL; + goto fail; } if (header.header_length > sizeof(header)) { @@ -530,12 +554,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, } s->refcount_order = header.refcount_order; - if (header.cluster_bits < MIN_CLUSTER_BITS || - header.cluster_bits > MAX_CLUSTER_BITS) { - error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits); - ret = -EINVAL; - goto fail; - } if (header.crypt_method > QCOW_CRYPT_AES) { error_setg(errp, "Unsupported encryption method: %i", header.crypt_method); @@ -546,9 +564,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, if (s->crypt_method_header) { bs->encrypted = 1; } - s->cluster_bits = header.cluster_bits; - s->cluster_size = 1 << s->cluster_bits; - s->cluster_sectors = 1 << (s->cluster_bits - 9); + s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */ s->l2_size = 1 << s->l2_bits; bs->total_sectors = header.size / 512; |